#include "Player.h"
#include "Common/AttrMgr/AttrMgr.h"
#include "base/core/Profiler.h"
#include "base/core/byte_buffer.h"
#include "Common/Utility/ServerTime.h"
#include "ProtoBuffer/AllProtocol.h"
#include "../LogicService.h"
#include "PlayerMgr.h"
#include "Common/TableData/RoleWarriorCfg.h"
#include "Common/TableData/RoleAssassinCfg.h"
#include "Common/TableData/RoleMasterCfg.h"
#include "Common/TableData/RoleShooterCfg.h"
#include "Common/TableData/RoleExpCfg.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "Common/TableData/TasktypeTasktypeCfg.h"

#include "Auctioneer/AuctioneerMgr.h"
#include "Duplicate/DuplicateMgr.h"
#include "Character/monster/MonsterRefCfg.h"

#include "Common/CharacterDefine.h"
#include "Character/drop/Drop.h"
#include "Character/drop/DropMgr.h"
#include "Character/object/Object.h"
#include "Common/TableData/AttributeAttributeCfg.h"
#include "Common/TableDataEx/MapCfg.h"
#include "Common/TableData/AreaAreaCfg.h"
#include "Common/TableData/FunctionunlockFunctionUnlockCfg.h"
#include "Common/CampDefine.h"
#include "Character/newAI/behaviac/CreatureCommonAI.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Common/Utility/TimeUtility.h"
#include "Common/TableData/RoleBornCfg.h"
#include "Common/Utility/AccountUtility.h"
#include "Character/TitlePart.h"
#include "Character/OperateLimitPart.h"
#include "Team/GTeamManager.h"
#include "ServerModule/LogicActivityModule.h"
#include "Character/horse/HorsePart.h"
#include "Scene/MapMgr.h"
#include "Common/ReliveMgr/ReliveMgr.h"
#include "Character/welfare/OperateWelfarePart.h"
#include "Common/TableData/FameFameCfg.h"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4244)
#endif

namespace{
	static const uint32_t s_saveSpaceTime = 60 * 4;     // 保存角色数据的时间间隔
}

#define NEW_PLAYER_MAX_LEVEL (30)
#define MAX_PLAYER_SPEED 100000  //玩家最大速度

#define MSG_HANDLE(min, max, value, func, condition)					\
	condition = false;											\
	((value) > (min) && (value) < (max)) ? condition = func : 0;\
	if (condition) \
		return true;    \

Player::Player()
	: m_deadIntervalTime(0)
	, m_createTime(0)
	, m_lastSaveTime(0)
	, m_onlineTime(0)
	, m_loginTime(0)
	, m_logoutTime(0)
	, m_uid(0)
	, m_chanId(0)	
	, m_pPlayerSession(nullptr)	
	, m_accountState(ACCOUNT_GAME_STATE_NULL)	
	, m_logoutFlag(LOGOUT_FLAG_NULL)
{
	m_creatureKind = CREATURE_PLAYER;
	m_bCanBeSeen = false;
	m_mapMsgFunc.clear();
	m_sightRange = MAX_CHARACTER_SINGLERANGE;
	//m_fspeed = 5.20f;
	m_isLastMove = false;
	m_lastHp = 0;
	m_unionName = "";
	m_strGuidelines = "";
	m_strPlot = "";
	m_buChanInfo.clear();
	m_attrClient.Clear();
	m_attrsCache.clear();
	m_attrs64Cache.clear();
	m_planeID = 0;
	m_fRadius = 0;
	m_vChangeAdvanceAttr.clear();
	m_vChangeBaseAttr.clear();
	m_nFightStatusTime=0;
	m_bAttack = false;

	m_iLeiGuaAllTime = 0;
	m_i64StartUseLeiGuaItem = 0;
	m_activeDailyData.Clear();
	m_activeData.Clear();
	m_setMissionPrestige.clear();

	const ConstantConstantCfgInfo *pConstCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_RevertHP_IntrvalTime);
	if (pConstCfg)
	{
		m_fRevertHpTime = pConstCfg->constantdata ;
	}

	const ConstantConstantCfgInfo *pConstCfgFightStatus = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_PlayerFightStatusTime);
	if (pConstCfgFightStatus)
	{
		m_nFightStatusTime= pConstCfgFightStatus->constantdata ;
	}

	//玩家非部件消息响应注册函数
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_ATRR_POINT] = &Player::C2AttrPoint;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_ATRR_CLEAR_POINT] = &Player::C2AttrClearPoint;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_AUTO_POINT] = &Player::C2AutoAttrPoint;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_RELIVE] = &Player::C2RelivePlayer;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_GUIDELINES] = &Player::C2SaveGuidelines;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_PLOT] = &Player::C2SavePlot;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_USE_MONSTER] = &Player::C2UseMonster;
	m_mapMsgFunc[CLIENT_TO_LOGIC_PLAYER_FETCH_MISSION_PRESTIGE] = &Player::FetchMissionPrestige;
	

}

Player::~Player()
{

}

bool Player::Init(CharacterDBInfo &PlayerInfo, CharLoginInfo* pLoginfo)
{
	memset(m_attrs, 0, sizeof(uint32_t)*P_MAX);
	memset(m_attrs64, 0, sizeof(uint64_t)*P_ATTR_ULONG_END);
	m_bIsNeedCalcFight = false;
	for (uint32_t i = 0; i < PART_MAX; i++)
	{
		m_pPart[i] = nullptr;
	}

	ReadBaseData(PlayerInfo);
	SetAccountInfo(pLoginfo);

	//SetSpeed(m_fspeed * 1000);

	//初始化角色等级相关属性
	InitLevAttrs();

	

	//速度和视野读表
	const RoleBornCfgInfo * pConfig = g_GetRoleBornCfg(m_attrs[P_PROF], m_attrs[P_GENDER]);
	if (!pConfig)
	{
		LogErrFmtPrint("player born config error prof=%d,gender=%d", m_attrs[P_PROF], m_attrs[P_GENDER]);
		return false;
	}
	SetAttrCache(g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, C_MSPEED), pConfig->mSpeed);
	m_attrs[P_MSPEED] = pConfig->mSpeed; //这里先赋值，因为宠物部件中，要用到的属性最终值，如果有其它的，还得在部件之前给最终值
	m_sightRange = pConfig->view /1000.0f;
	m_fRadius = pConfig->radius /1000.0f;
	//初始化玩家部件初始化 代码重构 fix by lian
	for (int32_t i = PART_OPERATELIMIT; i < PART_MAX; i++)
	{
		m_pPart[i] = g_GetCreatureMgr()->CreatePart(i, dynamic_cast<Creature*>(this), &PlayerInfo);
		if (!m_pPart[i])
		{
			continue;
		}
	}

	FinallyCalcChangeAttr();   //属性都赋值了，先计算一次

	//因为改变血量上限有可能改变当前值，所以把上线当前值的赋值放最后处理
	if (m_logoutTime>0)
	{
		m_attrs[P_HP] = PlayerInfo.basedata().hp();
		m_attrs[P_MP] = PlayerInfo.basedata().mp();
	}
	else
	{
		m_attrs[P_HP] = m_attrs[P_MAX_HP];
		m_attrs[P_MP] = m_attrs[P_MAX_MP];
	}

	m_isFightState = false;
	m_startFightStateTime = 0;
	//m_attrs[P_HP] = m_attrs[P_MAX_HP];
	//m_attrs[P_MP] = m_attrs[P_MAX_MP];


	


	//清空下广播列表，可能还没进这里的时候，有地方给广播列表赋值，此时，赋的值不是玩家最新的值，会显示错误
	//表现为刚进入时，显示不正常
	m_attrBroadcastClient.Clear();
	m_attrsCache.clear();
	m_attrs64Cache.clear();
	m_attrsBroadCastCache.clear();
	m_attrs64BroadCastCache.clear();

	//LogDebugFmtPrint("online hp=%d",m_attrs[P_HP]);

	//上线算一次战斗力
	CalcPlayerFightPower(false);

	g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_UNDER_ATTACK, m_Cid, 0, NULL);
	g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_ATTACK_SOMEBODY, m_Cid, 0, NULL);
	g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_CALC_FIGHT_POWER, m_Cid,CREATURE_PLAYER,"calc fightpower");

	g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_CREATURE_DEAD, m_Cid, CREATURE_MONSTER, "kill monster");

	//启回血定时器
	g_GetTimerAxis()->SetTimer(enTime_RevertHP, m_fRevertHpTime,this);

	return true;
}

void Player::Update(uint64_t tick)
{
	if (!GetCanBeSeenFlag())
	{
		return;
	}

	uint64_t curTick = g_GetGlobalServerTime()->Tick();
	Creature::Update(tick);
	
	//部件update
	for (int32_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
			m_pPart[i]->Update(tick);
	}

	//更新玩家状态
	//if (m_curstate == State_dead && m_reviveIntervalTime < curTick)
	//	OnNearBornRevive();

	if (m_isFightState && ( curTick-m_startFightStateTime>m_nFightStatusTime))
	{
		if (m_isFightState!=false)
		{
			m_isFightState = false;
			UpdateStateToClient();
		}
	}

	// 定时存DB
	if (ServerTime::UnixSec() >= (m_lastSaveTime + s_saveSpaceTime))
	{ 
		// 添加到分帧任务列表中
		Attach(TNID_SAVE_DB);
	}

	//处理同步
	if (GetAttr(C_TEAM_ID) > 0) //有队伍才同步
	{
		if (m_lastHp != (uint32_t)GetAttr(C_HP))
		{
			m_lastHp = (uint32_t)GetAttr(C_HP);
			Attach(TNID_SYNC_HP_CENTER);
		}
		/* 位置同步暂时先注释掉
		MovePart *pMove = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
		if (nullptr != pMove)
		{
			if (pMove->IsMoving()) //正在移动
			{
				m_isLastMove = true;
			}
			else if (m_isLastMove) //移动已经停止了，但是上一帧还在移动，再多同步一帧
			{
				m_isLastMove = false;
			}
		}*/

	}
}

bool Player::UnInit()
{
	DetachAll();
	m_isLastMove = false;
	m_lastHp = 0;

	m_lastSaveTime = 0;
	m_hostNode.SetHost(nullptr);

	//m_leaveGameSave = false;
	m_pPlayerSession = nullptr;
	//MMOLOG_OUTPUT_ERROR(!m_hostNode.IsLinked());

	//
	m_unionName.clear();
	m_setMissionPrestige.clear();

	for (int32_t i = PART_OPERATELIMIT; i < PART_MAX; i++)
	{
		if (m_pPart[i])
		{
			g_GetCreatureMgr()->RecylePart(m_pPart[i]);
			m_pPart[i] = nullptr;
		}
	}

	g_GetEvent()->UnSubscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_UNDER_ATTACK, m_Cid, 0);
	g_GetEvent()->UnSubscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_ATTACK_SOMEBODY, m_Cid, 0);
	g_GetEvent()->UnSubscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_CALC_FIGHT_POWER, m_Cid, CREATURE_PLAYER);
	g_GetEvent()->UnSubscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_CREATURE_DEAD, m_Cid, CREATURE_MONSTER);
	//CTODO 生物离开场景不应该在UnInit这里做
	Creature::UnInit();

	//启回血定时器
	g_GetTimerAxis()->KillTimer(enTime_RevertHP,this);
	g_GetTimerAxis()->KillTimer(enTime_Relive, this);
	g_GetTimerAxis()->KillTimer(enTime_LeiGua, this);
	
	return true;
}

Part* Player::GetPart(uint32_t partType) 
{
	if (partType >= PART_MAX || partType <= PART_NONE)
		return nullptr;

	if (!m_pPart[partType])
		return nullptr;

	return m_pPart[partType];
}

bool Player::OnMsgHandle(uint32_t cmd, const char* data, uint32_t len)
{
	//bool ret = false;
	//MSG_HANDLE(CLIENT_TO_LOGIC_SCENE_BEGIN, CLIENT_TO_LOGIC_SCENE_END, cmd, m_pPart[PART_MOVE]->OnMsgHandle(cmd, data, len), ret);
	//MSG_HANDLE(CLIENT_TO_LOGIC_SKILL_BEGIN, CLIENT_TO_LOGIC_SKILL_END, cmd, m_pPart[PART_SKILL]->OnMsgHandle(cmd, data, len), ret);
	//MSG_HANDLE(CLIENT_TO_LOGIC_PACKAGE_BEGIN, CLIENT_TO_LOGIC_PACKAGE_END, cmd, m_pPart[PART_PACKAGE]->OnMsgHandle(cmd, data, len), ret);
	//MSG_HANDLE(CLIENT_TO_LOGIC_MISSION_BEGIN, CLIENT_TO_LOGIC_MISSION_END, cmd, m_pPart[PART_MISSION]->OnMsgHandle(cmd, data, len), ret);
	//MSG_HANDLE(CLIENT_TO_LOGIC_CHAT_BEGIN, CLIENT_TO_LOGIC_CHAT_END, cmd, m_pPart[PART_CHAT]->OnMsgHandle(cmd, data, len), ret);
	//MSG_HANDLE(CLIENT_TO_LOGIC_DUPLICATE_BEGIN, CLIENT_TO_LOGIC_DUPLICATE_END, cmd, m_pPart[PART_DUPLICATE]->OnMsgHandle(cmd, data, len), ret);
	MsgFunc::iterator iter = m_mapMsgFunc.find(cmd);
	if (iter != m_mapMsgFunc.end())
		(this->*m_mapMsgFunc[cmd])(data, len);
	return  true;
}

bool Player::AddAttr(uint32_t CANum, int64_t attrValue, bool syn, uint64_t relationCid /* = 0 */)
{
	const char* currencyName = g_GetAttrMgr()->GetCurrencyName(CANum);
	if (currencyName)
	{
		LogErrFmtPrint("Player::AddAttr cannt add currencytype %d, %s", CANum, currencyName);
		return false;
	}

	uint32_t PANum = g_GetAttrMgr()->GetPAttr(CANum);


	return AddAttrPA(PANum, attrValue, syn, relationCid);
}
bool Player::AddAttrCache(uint32_t CANum, int64_t attrValue, uint64_t relationCid /* = 0 */)
{
	uint32_t PANum = g_GetAttrMgr()->GetPAttr(CANum);
	return AddAttrPACache(PANum, attrValue, relationCid);
}

bool Player::AddAttrPA(uint32_t PANum, int64_t attrValue, bool syn, uint64_t relationCid /* = 0 */)
{
	if (AddAttrPACache(PANum, attrValue, relationCid))
	{
		if (syn)
		{
			SynAttrToClient();
		}
		return true;
	}
	
	return false;
}

bool Player::AddAttrPACache(uint32_t PANum, int64_t attrValue, uint64_t relationCid /* = 0 */)
{
	if (PANum <= P_NONE || PANum >= P_MAX)
		return false;

	int64_t oldAttrVal = GetPAttrValue(PANum);
	//满了，则不用再加
	if (attrValue>0)
	{
		if (PANum == P_HP)
		{
			if (m_attrs[PANum] == m_attrs[P_MAX_HP])
				return false;
		}
		else if (PANum == P_MP)
		{
			if (m_attrs[PANum] == m_attrs[P_MAX_MP])
				return false;
		}

		//如果是金币和钻石做上限控制，策划要求
		if (m_attrs64[P_GOLD] >= INT64_MAX  /*pow(2, 63)*/)
		{
			//不让加，直接给邮件
			return false;
		}
		
		if (m_attrs[P_DIAMOND] >= INT32_MAX /*pow(2,31)*/ )
		{
			return false;
		}
	}
	
	if (PANum>P_ATTR_ULONG_END)
	{
		if (m_attrs[PANum]>INT32_MAX)
		{
			return false;
		}
		m_attrs[PANum] += attrValue;
		if (!IsCanNegativeAttr(PANum) && PANum<P_CLIENT_END) //是否是允许负数的属性
		{
			m_attrs[PANum] = m_attrs[PANum] > 0 ? m_attrs[PANum] : 0;
		}
	}
	else
	{
		if (m_attrs64[PANum]>INT64_MAX)
		{
			return false;
		}
		m_attrs64[PANum] += attrValue;
		m_attrs64[PANum] = m_attrs64[PANum] > 0 ? m_attrs64[PANum] : 0;
	}
	

	if (PANum == P_HP)
	{
		m_attrs[PANum] = m_attrs[PANum] > m_attrs[P_MAX_HP] ? m_attrs[P_MAX_HP] : m_attrs[PANum];
	}
	else if (PANum == P_MP)
	{
		m_attrs[PANum] = m_attrs[PANum] > m_attrs[P_MAX_MP] ? m_attrs[P_MAX_MP] : m_attrs[PANum];
	}

	if (PANum == P_MAX_HP)
	{
		if (m_attrs[P_MAX_HP] < m_attrs[P_HP])
		{
			m_attrs[P_HP] = m_attrs[P_MAX_HP];
		}
		else if (m_attrs[P_MAX_HP] - attrValue>0)
		{
			//当前血量按比例增减
			m_attrs[P_HP] = (m_attrs[P_HP] * 1.0 / (m_attrs[P_MAX_HP] - attrValue))*m_attrs[P_MAX_HP];
		}
		SynAttrCache(P_HP);
	}
	else if (PANum == P_MAX_MP)
	{
		if (m_attrs[P_MAX_MP] < m_attrs[P_MP])
		{
			m_attrs[P_MP] = m_attrs[P_MAX_MP];
		}
		else if (m_attrs[P_MAX_MP] - attrValue>0)
		{
			//当前蓝量按比例增减
			m_attrs[P_MP] = (m_attrs[P_MP] * 1.0 / (m_attrs[P_MAX_MP] - attrValue))*m_attrs[P_MAX_MP];
		}
		SynAttrCache(P_MP);
	}

	//加法映射器
	//if (!AttrsFormula(PANum, relationCid, true))
	{
		//if (!FinalAtrrFormula(PANum, relationCid, true)) //最终值属性映射器
		{
			AdvanceAttrFormula(PANum, attrValue); //高级属性映射器
		}
	}

	//这里作这个特殊判断，主要是有几个加点属性，放在基本属性里，但是算法又和其它模块的中间算法一样，所以这里要做特殊判断
	if (PANum<P_CLIENT_END && (PANum<P_AUTO_ATTR_POWER || PANum>P_ATTR_POINT_PRECISION))  //只有基础属性同步
	{
		SynAttrCache(PANum);

		if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), PANum) == m_vChangeBaseAttr.end())
		{
			m_vChangeBaseAttr.push_back(PANum);
		}
	}
	else
	{

		if (std::find(m_vChangeAdvanceAttr.begin(), m_vChangeAdvanceAttr.end(), PANum) == m_vChangeAdvanceAttr.end())
		{
			m_vChangeAdvanceAttr.push_back(PANum);
		}

		if (PANum<P_CLIENT_END)
		{
			SynAttrCache(PANum);
		}
	}


	if (PANum == P_HP && m_attrs[PANum] == 0)
		OnDead(relationCid);


	if (PANum < P_CLIENT_END)
	{
		int64_t changeAttrValue = GetPAttrValue(PANum) - oldAttrVal;
		//发送属性改变事件
		TitlePart * pPart = dynamic_cast<TitlePart*>(m_pPart[PART_TITLE]);
		if (pPart)
		{
			pPart->DoAttrTitle(PANum, GetPAttrValue(PANum));
		}
		AchievementPart *pAchievePart = dynamic_cast<AchievementPart*>(m_pPart[PART_ACHIEVEMENT]);
		if (pAchievePart)
		{
			pAchievePart->DoAttrChange(PANum, GetPAttrValue(PANum), attrValue);
		}
		OperateLimitPart *pOperatLimitPart = dynamic_cast<OperateLimitPart*>(m_pPart[PART_OPERATELIMIT]);
		if (nullptr != pOperatLimitPart)
		{
			pOperatLimitPart->OnAttrChange(PANum, changeAttrValue);
		}
		//if (m_bIsNeedCalcFight==false && IsNeedCalcFightAttr(PANum))
		//{
		//	m_bIsNeedCalcFight = true;
		//}

	}

	return true;
}


bool   Player::IsCanNegativeAttr(uint32_t attrPANum)
{
	if (attrPANum == P_SPEED_PERCENT || attrPANum == P_MAXHPRATE
		|| attrPANum == P_MAXMPRATE || attrPANum == P_APRATE  
		|| attrPANum == P_MATRATE || attrPANum == P_DPRATE
		|| attrPANum == P_MDPRATE)
	{
		return true;
	}

	return false;
}

//是否是需要计算战斗力属性
bool   Player::IsNeedCalcFightAttr(uint32_t attrPANum)
{
	static vector<uint32_t> vFightAttr;

	bool isConfig = true;
	if ((int)vFightAttr.size() > 0)
	{
		isConfig = false;
	}
	if (isConfig)
	{
		for (int i = C_POWER; i < (int)C_CHARACTER_PRO; ++i)
		{
			const AttributeAttributeCfgInfo * pConfig = g_GetAttributeAttributeCfgTable()->GetAttributeAttributeCfgInfo(i);
			if (pConfig && pConfig->vec_profForbid[m_attrs[P_PROF] - 1] == 1)
			{
				vFightAttr.push_back(g_GetAttrMgr()->GetPAttr(i));
			}
		}
	}

	if (std::find(vFightAttr.begin(), vFightAttr.end(), attrPANum) != vFightAttr.end())
	{
		return true;
	}
	return false;
}

//是否是战斗属性，战斗属性在调属性修改时，他修改的相关所有属性都不用计算战斗力
bool   Player::IsFightAttr(uint32_t attrPNum)
{
	//暂时定技能和buff属性不更新战力
	if ((attrPNum <= P_CLIENT_END + (enFightAttrModule_Skill)*C_FIGHT_ATTR_END && attrPNum >= P_CLIENT_END + (enFightAttrModule_Skill - 1)*C_FIGHT_ATTR_END)
		|| (attrPNum <= P_CLIENT_END + (enFightAttrModule_Buff)*C_FIGHT_ATTR_END && attrPNum >= P_CLIENT_END + (enFightAttrModule_Buff - 1)*C_FIGHT_ATTR_END))
	{
		return true;
	}

	return false;
}

void   Player::SetSpeed(float f, bool isSync)
{
	//m_fspeed = f;
	//if (isSync)
	//{
	//SetAttrPA(g_GetAttrMgr()->GetPlayerLevPAttr(C_MSPEED), f * 1000, isSync);
	//}
	//LogDebugFmtPrint("set speed  = %f cid=%llu", m_fspeed, m_Cid);
}


bool Player::CheckAttrValue(uint32_t CANum, uint32_t attrValue)
{
	uint32_t PANum = g_GetAttrMgr()->GetPAttr(CANum);
	if (P_NONE == PANum)
		return false;
	if (PANum>P_ATTR_ULONG_END)
	{
		return (int32_t)(m_attrs[PANum] - attrValue) >= 0 ? true : false;
	}
	else
	{
		return (int64_t)(m_attrs64[PANum] - attrValue) >= 0 ? true : false;
	}
}


void Player::OnDead(uint64_t killerCid)
{
	m_deadIntervalTime = Time::Now().UnixSec();
	g_GetEvent()->FireExecute(EVENT_CREATURE_WILLING_DIED, m_Cid, 0, nullptr, 0);
	if (GetAttr(C_HP) > 0)
	{
		return;
	}

	m_curstate = State_dead;

	Creature * pCreature = g_GetCreatureMgr()->GetCreature(killerCid);
	if (pCreature)
	{
		if (pCreature->CreatureKind() == CREATURE_PLAYER || pCreature->CreatureKind() == CREATURE_REBOT)
		{
			Player * pPlayer = dynamic_cast<Player*>(pCreature);
			if (pPlayer)
			{
				m_attrBroadcastClient.set_name(pPlayer->GetName());
			}
		}
		else
		{
			m_attrBroadcastClient.set_killerconfigid(pCreature->GetConfigId());
		}

	}
	//m_attrsBroadCastCache[P_HP] = 0;

	//角色死亡掉落，因为要提示前端掉落的物品，所以改到这里直接调用
	MAP_UINT32_INT32 mapDropItem;
	mapDropItem.clear();
	bool removeItemFlag = false;
	SDropSourcePram source;
	g_GetDropMgr()->OnPlayerDieDrop(this, killerCid, mapDropItem, removeItemFlag, source);


	for (MAP_UINT32_INT32::iterator iter = mapDropItem.begin(); iter != mapDropItem.end();++iter)
	{
		stDropInfo* pInfo=m_attrBroadcastClient.add_dropinfo();
		pInfo->set_itemid(iter->first);
		pInfo->set_itemnum(iter->second);
	}

	if (removeItemFlag)
	{
		m_attrBroadcastClient.set_usedeaditem(1);
	}

	BuffEffect_CleanupAllFadeOutEffects(BuffInfoDeadEnd);
	SynAttrToClient();
	//Creature::OnDead(killerCid);

	PvpPart* pPvpPart = dynamic_cast<PvpPart*>(this->GetPart(PART_PVP));
	if (pPvpPart)
	{
		pPvpPart->CountPkKillingValue(killerCid, m_Cid);
		pPvpPart->ClearAllRedPlayer();
	}

	DieEvent dieEvent;
	dieEvent.killerCid = killerCid;
	dieEvent.count = 1;
	dieEvent.sceneId = m_sceneId;
	dieEvent.nCid = m_Cid;
	/*
	玩家死亡事件
	nSrcID:		玩家cid
	bySrcType:	玩家生物类型
	*/
	g_GetEvent()->FireExecute(EVENT_CREATURE_DEAD, m_Cid, m_creatureKind, (DieEvent*)&dieEvent, sizeof(dieEvent));

	//死亡状态通知到中心服
	GWLifeStatusNotify notify;
	notify.set_charid(m_Cid);
	notify.set_lifestatus(State_dead);
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_SERV_SYS, LOGIC_TO_CENTER_LIFE_STATUS_NOTIFY, &notify);

	//LogDebugFmtPrint("player ondead, cid:%lu,m_curstate=%d", m_Cid, m_curstate)

	//m_reviveIntervalTime = g_GetGlobalServerTime()->Tick() + pConstCfg->constantdata*1000; //20秒复活时间

	if (m_attrs[P_DUPLICATE_ID] == 0)
	{
		//const ConstantConstantCfgInfo *pConstCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_StaticMap_ReliveTime);
		//if (nullptr == pConstCfg)
		//{
		//	LogErrFmtPrint("[logicserver] Player::OnDead...nullptr == pConstCfg....EArg_StaticMap_ReliveTime:%d ", EArg_StaticMap_ReliveTime);
		//	return;
		//}

		const MapMapCfgInfo * pMapInfo = g_GetMapMapCfgTable()->GetMapMapCfgInfo(m_mapId);
		if (pMapInfo && pMapInfo->reviveTime>0)
		{
			g_GetTimerAxis()->SetTimer(enTime_Relive, pMapInfo->reviveTime * 1000, this, 1);
		}
		else
		{
			LogDebugFmtPrint(" map error get relive time");
		}
	}
	////如果有位面，则离开位面
	//if (GetPlaneID()>0)
	//{
	//	g_GetPlaneMgr()->LeavePlane(m_Cid);
	//}
}

void Player::OnTimer(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case enTime_Relive:
	{
		OnNearBornRevive();
		g_GetTimerAxis()->KillTimer(enTime_Relive, this);
	}
		
		break;
	case enTime_RevertHP:
	{
		//血量恢复之类 ,非战斗状态才能回血
		if ((m_curstate != State_dead) &&
			(m_isFightState ==false ) &&
			((GetAttr(C_MP) < GetAttr(C_MAX_MP)) || (GetAttr(C_HP) < GetAttr(C_MAX_HP))))
		{
			if (GetAttr(C_HP) < GetAttr(C_MAX_HP))
			{
				AddAttrCache(C_MP, (int32_t)(GetAttr(C_RESTORE_MP)));
				AddAttr(C_HP, (uint32_t)GetAttr(C_RESTORE_HP), true);
			}
			else
			{
				AddAttr(C_MP, (int32_t)(GetAttr(C_RESTORE_MP)), true);
			}
		}
	}
	break;
	case enTime_LeiGua:
	{
		m_iLeiGuaAllTime = 0;
		m_i64StartUseLeiGuaItem = 0;
		SyncLeiGuaLeftTimeToClient(0);
	}
	break;
	default:
		break;
	}
}


//获取复活点坐标和地图
bool Player::OnGetNearBornReliveInfo(uint32_t &nMapId,uint32_t & nSceneId, Point3<float> & nPos)
{
	uint32_t killValue = 0;
	PvpPart * pPvpPart = dynamic_cast<PvpPart*>(m_pPart[PART_PVP]);
	if (pPvpPart)
	{
		killValue = pPvpPart->GetPkKillingValue();
	}
	return g_GetReliveMgr()->GetDeadReliveInfoEx(GetMapId(), GetSceneId(), GetPos(), GetCampId(), killValue, nMapId, nSceneId, nPos);

	/*//检测有没PK惩罚
	PvpPart * pPvpPart = dynamic_cast<PvpPart*>(m_pPart[PART_PVP]);
	if (pPvpPart)
	{
		if (pPvpPart->GetPKValuePunishInfo(nSceneId, nPos))
		{
			return true;
		}
	}
	//新加需求，死亡复活先找他父地图，有直接复活在他父地图中
	uint32_t reliveMapId = m_mapId;
	const MapMapCfgInfo * pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(m_mapId);
	if (pMapCfg)
	{
		uint32_t tmpMap = CommonApi::StrToInt(pMapCfg->parentMap);
		if (tmpMap > 0)
		{
			reliveMapId = tmpMap;
		}
	}
	//复活到该地图的复活点
	Point3<float> pos = g_GetMapLocationCfg()->GetNearRelivePos(reliveMapId, m_pos, m_attrs[P_CAMP_ID]);
	if (pos.length() <= 0)
	{
		//直接找默认的地图复活
		const ConstantConstantCfgInfo *pConstCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_Relive_Default_MapID);
		if (pConstCfg)
		{
			pos = g_GetMapLocationCfg()->GetNearRelivePos(pConstCfg->constantdata, m_pos, m_attrs[P_CAMP_ID]);
			if (pos.length() <= 0)
			{
				return false;
			}
			else
			{
				MovePart * pPart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
				if (pPart)
				{
					nSceneId = pConstCfg->constantdata;
					nPos = pos;
					return true;
				}
			}
		}
	}
	else
	{
		if (reliveMapId == m_mapId)
		{

			nSceneId = m_sceneId;
			nPos = pos;
		}
		else
		{
			MovePart * pPart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
			if (pPart)
			{
				nSceneId = reliveMapId;
				nPos = pos;
			}
		}
	}

	return true;*/
}


//最近复活点复活
bool Player::OnNearBornRevive()
{
	//检测有没PK惩罚
	PvpPart * pPvpPart = dynamic_cast<PvpPart*>(m_pPart[PART_PVP]);
	if (pPvpPart)
	{
		if (pPvpPart->PKValuePunish())
		{
			return true;
		}
	}


	uint32_t nSceneId = 0;
	uint32_t nMapId = 0;
	Point3<float> pos(0.0, 0.0, 0.0);
	if (OnGetNearBornReliveInfo(nMapId,nSceneId, pos))
	{
		MovePart * pPart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
		if (pPart)
		{// OnGetNearBornReliveInfo 返回的复活地图ID一定是静态地图，所以这里 地图ID和场景ID相同
			STransParam transParam;
			transParam.srcMapId = GetMapId();
			transParam.transType = ETransType_Relive;
			pPart->TransScene(nSceneId, pos, nMapId, transParam);
			OnRevive(m_Cid);
			return true;
		}
		else
		{
			LogErrFmtPrint("Player::OnNearBornRevive...nullptr == pPart...cid:%lu, curmap:%u, curscene:%u, nMapId:%u, nSceneId:%u ", m_Cid, m_mapId, m_sceneId, nMapId, nSceneId);
		}
	}
	else
	{
		PlayerReliveResponse msgRsp;
		msgRsp.set_retcode(RET_RELIVE_POS_NOT_FIND);
		SendDataToClient(LOGIC_TO_CLIENT_RELIVE_RESULT, &msgRsp);
	}

	
	return false;
}





void Player::OnRevive(uint64_t saverCid)
{
	SetAttr(C_HP, m_attrs[P_MAX_HP]);  //先满血复活
	SetAttr(C_MP, m_attrs[P_MAX_MP]);  //满蓝复活

	Attr *patts = m_attrBroadcastClient.add_creatureattrs();
	patts->set_attrnum(P_HP);
	patts->set_attrvalue(m_attrs[P_MAX_HP]);
	Attr *pattsMaxHp = m_attrBroadcastClient.add_creatureattrs();
	pattsMaxHp->set_attrnum(P_MAX_HP);
	pattsMaxHp->set_attrvalue(m_attrs[P_MAX_HP]);
	Attr *pattrmp = m_attrBroadcastClient.add_creatureattrs();
	pattrmp->set_attrnum(P_MP);
	pattrmp->set_attrvalue(m_attrs[P_MAX_MP]);
	Attr *pattrmpMaxMp = m_attrBroadcastClient.add_creatureattrs();
	pattrmpMaxMp->set_attrnum(P_MAX_MP);
	pattrmpMaxMp->set_attrvalue(m_attrs[P_MAX_MP]);


	

	Creature::OnRevive(saverCid);

	m_deadIntervalTime = 0;

	g_GetTimerAxis()->KillTimer(enTime_Relive, this);

	//复活事件
	ReliveEvent reliveEvent;
	reliveEvent.cid = GetCid();
	g_GetEvent()->FireExecute(EVENT_CREATURE_REVIVE, GetCid(), CREATURE_PLAYER, &reliveEvent, sizeof(ReliveEvent));
}

void Player::OnRevive(CharIDType saverCid, int64_t curHp, int64_t curMp)
{
	SetAttr(C_HP, curHp);  //先满血复活
	SetAttr(C_MP, curMp);  //满蓝复活

	Attr *patts = m_attrBroadcastClient.add_creatureattrs();
	patts->set_attrnum(P_HP);
	patts->set_attrvalue(m_attrs[P_HP]);
	Attr *pattrmp = m_attrBroadcastClient.add_creatureattrs();
	pattrmp->set_attrnum(P_MP);
	pattrmp->set_attrvalue(m_attrs[P_MP]);


	Creature::OnRevive(saverCid); //同步广播属性
	g_GetTimerAxis()->KillTimer(enTime_Relive, this);

	m_deadIntervalTime = 0;

	//复活事件
	ReliveEvent reliveEvent;
	reliveEvent.cid = GetCid();
	g_GetEvent()->FireExecute(EVENT_CREATURE_REVIVE, GetCid(), CREATURE_PLAYER, &reliveEvent, sizeof(ReliveEvent));
}


void Player::SetAttr(uint32_t CANum, int64_t attrValue, bool syn /* = false */)
{
	uint32_t PANum = g_GetAttrMgr()->GetPAttr(CANum);
	SetAttrPA(PANum, attrValue, syn);
}
void Player::SetAttrCache(uint32_t CANum, int64_t attrValue)
{
	uint32_t PANum = g_GetAttrMgr()->GetPAttr(CANum);
	SetAttrPACache(PANum, attrValue);
}
void Player::SetAttrPA(uint32_t PANum, int64_t attrValue, bool syn /* = false */, bool isCalc )
{
	SetAttrPACache(PANum, attrValue,isCalc);
	if (syn)
	{
		SynAttrToClient();
	}
}
void Player::SetAttrPACache(uint32_t PANum, int64_t attrValue, bool isCalc)
{
	if (P_NONE == PANum  || PANum >= P_MAX)
		return;
	int64_t oldAttrValue = GetPAttrValue(PANum);
	if (PANum == P_MAX_HP && m_attrs[PANum]>0)
	{
		if (attrValue < m_attrs[P_HP])
		{
			m_attrs[P_HP] = attrValue;
		}
		else
		{
			//当前血量按比例增减
			m_attrs[P_HP] = (m_attrs[P_HP] * 1.0 / (m_attrs[P_MAX_HP]))*attrValue;
		}

		SynAttrCache(P_HP);
	}
	else if (PANum == P_MAX_MP && m_attrs[PANum]>0)
	{
		if (attrValue < m_attrs[P_MP])
		{
			m_attrs[P_MP] = attrValue;
		}
		else
		{
			//当前蓝按比例增减
			m_attrs[P_MP] = (m_attrs[P_MP] * 1.0 / (m_attrs[P_MAX_MP]))*attrValue;
		}
		SynAttrCache(P_MP);
	}

	if (PANum>P_ATTR_ULONG_END)
	{
		if (!IsCanNegativeAttr(PANum) && PANum<P_CLIENT_END) //允许为负的不管
		{
			m_attrs[PANum] = attrValue > 0 ? attrValue : 0;
		}
		else
		{
			m_attrs[PANum] = attrValue;
		}
		
	}
	else
	{
		m_attrs64[PANum] = attrValue > 0 ? attrValue : 0;
	}

	
	if (PANum == P_HP && m_attrs[PANum] > m_attrs[P_MAX_HP])
	{
		m_attrs[PANum] = m_attrs[P_MAX_HP];
	}
	else if (PANum == P_MP && m_attrs[PANum] > m_attrs[P_MAX_MP])
	{
		m_attrs[PANum] = m_attrs[P_MAX_MP];
	}
	
	AdvanceAttrFormula(PANum, attrValue); //高级属性映射器

	if (PANum < P_CLIENT_END && (PANum<P_AUTO_ATTR_POWER || PANum>P_ATTR_POINT_PRECISION))  //只有基础属性同步
	{
		SynAttrCache(PANum);

		if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), PANum) == m_vChangeBaseAttr.end())
		{
			m_vChangeBaseAttr.push_back(PANum);
		}
		
	}
	else
	{
		if (std::find(m_vChangeAdvanceAttr.begin(), m_vChangeAdvanceAttr.end(), PANum) == m_vChangeAdvanceAttr.end())
		{
			m_vChangeAdvanceAttr.push_back(PANum);
		}
		
		if (PANum < P_CLIENT_END)
		{
			SynAttrCache(PANum);
		}
	}

	//只有主要属性改变通知，后面一些中间属性改变不作通知，减少事件发送
	if (PANum < P_CLIENT_END) 
	{
		int64_t changeAttrValue = GetPAttrValue(PANum) - oldAttrValue;
		//BEGIN_PROFILE("event change title");
		TitlePart * pPart = dynamic_cast<TitlePart*>(m_pPart[PART_TITLE]);
		if (pPart)
		{
			pPart->DoAttrTitle(PANum, attrValue);
		}
		//END_PROFILE();

		//BEGIN_PROFILE("event change achivement");
		AchievementPart *pAchievePart = dynamic_cast<AchievementPart*>(m_pPart[PART_ACHIEVEMENT]);
		if (pAchievePart)
		{
			pAchievePart->DoAttrChange(PANum, attrValue);
		}
		//END_PROFILE();
		OperateLimitPart *pOperateLimitPart = dynamic_cast<OperateLimitPart*>(m_pPart[PART_OPERATELIMIT]);
		if (nullptr != pOperateLimitPart)
		{
			pOperateLimitPart->OnAttrChange(PANum, changeAttrValue);
		}
	}
}


void Player::FinallyCalcChangeAttr()
{
	bool bFindFightAttr = false;
	//先把中间属性加到基础属性上
	for (int i = 0;i< (int)m_vChangeAdvanceAttr.size();++i)
	{
		if (m_vChangeAdvanceAttr[i]>0)
		{
			if (IsFightAttr(m_vChangeAdvanceAttr[i]))
			{
				bFindFightAttr = true;
			}
			AttrsFormula(m_vChangeAdvanceAttr[i]);
		}
	}
	m_vChangeAdvanceAttr.clear();

	FinalAtrrFormula();

	//由战斗属性所带来的改变，不用计算战斗力
	if (!bFindFightAttr)
	{
		for (int i = 0; i < (int)m_vChangeBaseAttr.size(); ++i)
		{
			if (m_bIsNeedCalcFight == false && IsNeedCalcFightAttr(m_vChangeBaseAttr[i]))
			{
				m_bIsNeedCalcFight = true;
				break;
			}
		}
	}


	m_vChangeBaseAttr.clear();
}


int64_t Player::GetAttr(uint32_t CANum) 
{
	//公共属性id转换玩家属性id
	uint32_t PANum = g_GetAttrMgr()->GetPAttr(CANum);
	return GetPAttrValue(PANum);
}

int64_t Player::GetPAttrValue(uint32_t attrPANum)
{
	if (attrPANum > P_NONE && attrPANum < P_MAX)
	{
		if (attrPANum>P_ATTR_ULONG_END)
		{
			return m_attrs[attrPANum];
		}
		else
			return m_attrs64[attrPANum];
	}
	return 0;
}

uint32_t Player::GetAttrNum(uint32_t CommonAttrNum)
{
	return g_GetAttrMgr()->GetPAttr(CommonAttrNum);
}

//属性处理
void Player::SynAttrCache(uint32_t PANum)
{
	if (g_GetAttrMgr()->IsBroadcastPAttr(PANum))
	{
		if (PANum>P_ATTR_ULONG_END)
		{
			m_attrsBroadCastCache[PANum] = m_attrs[PANum];
		}
		else
		{
			m_attrs64BroadCastCache[PANum] = m_attrs64[PANum];
		}
	}
	else
	{
		if (PANum > P_ATTR_ULONG_END)
		{
			m_attrsCache[PANum] = m_attrs[PANum];
		}
		else
		{
			m_attrs64Cache[PANum] = m_attrs64[PANum];
		}
	}
		
}

void Player::SynAttr()
{
	if (m_attrsCache.empty() && m_attrs64Cache.empty())
		return;

	Uint32Map::iterator iter = m_attrsCache.begin();
	for (; iter != m_attrsCache.end(); iter++)
	{
		Attr *pAttr = m_attrClient.add_creatureattrs();
		if (nullptr != pAttr)
		{
			pAttr->set_attrnum(iter->first);
			pAttr->set_attrvalue(iter->second);
		}		
	}

	Uint64Map::iterator iter64 = m_attrs64Cache.begin();
	for (; iter64 != m_attrs64Cache.end(); iter64++)
	{
		Attr64 *pAttr64 = m_attrClient.add_creatureattrs64();
		if (nullptr != pAttr64)
		{
			pAttr64->set_attrnum(iter64->first);
			pAttr64->set_attrvalue(iter64->second);
		}
	}

	if (!SendDataToClient(EMODULE_ID_PLAYER, LOGIC_TO_CLIENT_CREATURE_SYN_ATTR, (ProtoBufBase*)(&m_attrClient)))
	{
		LogErrFmtPrint("Player::SynAttr, err, cid:%lu, attrsCacheSize:%d, attrs64CacheSize:%d, attrClientSize:%d", m_Cid, m_attrsCache.size(), m_attrs64Cache.size(), m_attrClient.ByteSize());
	}
	m_attrsCache.clear();
	m_attrs64Cache.clear();
	m_attrClient.clear_creatureattrs();
	m_attrClient.clear_creatureattrs64();

	//LogInfoFmtPrint("Player::SynAttr info cid:%lu, attrsCacheSize : %d, attrs64CacheSize : %d, attrClientSize : %d", m_Cid, m_attrsCache.size(), m_attrs64Cache.size(), m_attrClient.ByteSize() );
}

bool Player::AdvanceAttrFormula(uint32_t PANum, int64_t nValue)
{
	std::unordered_map<uint32_t, uint32_t> *pMap = g_GetAttrMgr()->GetAdvanceAttrsAgrs(m_attrs[P_PROF], PANum);
	if (!pMap)
		return false;
	
	std::unordered_map<uint32_t, uint32_t>::iterator iter = pMap->begin();
	for (; iter != pMap->end(); iter++)
	{
		uint32_t value = 0;
		//value = m_attrs[PANum]*iter->second / 10000;

		//只缓存，同步客户端在外层处理  ,这里可能多个属性影响一个属性
		std::unordered_map<uint32_t, uint32_t> tmpMap;
		g_GetAttrMgr()->GetAdvanceAttrsBeAdd(m_attrs[P_PROF], iter->first, tmpMap);
		std::unordered_map<uint32_t, uint32_t>::iterator iterMap = tmpMap.begin();
		for (; iterMap != tmpMap.end(); ++iterMap)
		{
			value += m_attrs[iterMap->first] * iterMap->second / 10000.0f;
		}
		SetAttrPACache(iter->first, value);
	}
	return true;
}

bool Player::AttrsFormula(uint32_t PANum)
{
	AttrMgr::VecAttr *pVecMap = g_GetAttrMgr()->GetPAddAtrrsFormula(PANum);
	if (!pVecMap || pVecMap->size() < 2)
		return false;

	AttrMgr::VecAttr& vecMap = *pVecMap;

	int64_t value = 0;


	if (vecMap[0] == P_HP ||
		vecMap[0] == P_MP)
	{
		return false;
	}

	for (uint32_t i = 1; i < vecMap.size(); i++)
	{
		value += m_attrs[vecMap[i]];

		//将cache中的相同的去掉
		VEC_UINT32::iterator iter = std::find(m_vChangeAdvanceAttr.begin(), m_vChangeAdvanceAttr.end(), vecMap[i]);
		if (iter!=m_vChangeAdvanceAttr.end())
		{
			*iter = 0;
		}
	}
	SetAttrPACache(vecMap[0], value);
	return true;
}

bool Player::FinalAtrrFormula()
{
	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MAXHPRATE) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MAX_HP) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_MAX_HP);

		m_attrs[P_MAX_HP] = m_attrs[P_MAX_HP] * (1 + m_attrs[P_MAXHPRATE] / 10000.0f);
		m_attrs[P_HP] = m_attrs[P_HP] * (1 + m_attrs[P_MAXHPRATE] / 10000.0f);

		SynAttrCache(P_HP);
		SynAttrCache(P_MAX_HP);
	}

	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MAXMPRATE) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MAX_MP) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_MAX_MP);

		m_attrs[P_MAX_MP] = m_attrs[P_MAX_MP] * (1 + m_attrs[P_MAXMPRATE] / 10000.0f);
		m_attrs[P_MP] = m_attrs[P_MP] * (1 + m_attrs[P_MAXMPRATE] / 10000.0f);
		SynAttrCache(P_MP);
		SynAttrCache(P_MAX_MP);
	}

	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_APRATE) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_AP) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_AP);
		m_attrs[P_AP] = m_attrs[P_AP] * (1 + m_attrs[P_APRATE] / 10000.0f);
		SynAttrCache(P_AP);
	}

	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MATRATE) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MAT) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_MAT);
		m_attrs[P_MAT] = m_attrs[P_MAT] * (1 + m_attrs[P_MATRATE] / 10000.0f);
		SynAttrCache(P_MAT);
	}

	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_DPRATE) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_DP) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_DP);
		m_attrs[P_DP] = m_attrs[P_DP] * (1 + m_attrs[P_DPRATE] / 10000.0f);
		SynAttrCache(P_DP);
	}

	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MDPRATE) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MDP) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_MDP);
		m_attrs[P_MDP] = m_attrs[P_MDP] * (1 + m_attrs[P_MDPRATE] / 10000.0f);
		SynAttrCache(P_MDP);
	}

	if (std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_SPEED_PERCENT) != m_vChangeBaseAttr.end() ||
		std::find(m_vChangeBaseAttr.begin(), m_vChangeBaseAttr.end(), P_MSPEED) != m_vChangeBaseAttr.end())
	{
		AttrsFormula(P_MSPEED);
		m_attrs[P_MSPEED] = m_attrs[P_MSPEED] * (1 + m_attrs[P_SPEED_PERCENT] / 10000.0f);
		if (m_attrs[P_MSPEED]>MAX_PLAYER_SPEED)
		{
			m_attrs[P_MSPEED] = MAX_PLAYER_SPEED;
		}
		SynAttrCache(P_MSPEED);
	}

	/*//其它有些模块有改动战斗属性，但是由于改动的属性类型比较少，先放这里单独处理下
	//亲密值影响攻击
	if (m_attrs[P_TEAM_ID]>0 && m_attrs[P_CLOSENESS_LEVEL]>0)
	{
		uint32_t pAttack=g_GetGTeamMgr()->GetTeamAttackAdd(m_attrs[P_CLOSENESS_LEVEL]);
		if (m_attrs[P_PROF] == ECHARACTER_PROF_WARRIOR || m_attrs[P_PROF] == ECHARACTER_PROF_ASSASSIN)
		{
			m_attrs[P_MAT] += pAttack;
			SynAttrCache(P_MAT);
		}
		else
		{
			m_attrs[P_AP] += pAttack;
			SynAttrCache(P_AP);
		}
	}*/

	return true;
}


float Player::CalcAttrFightPower(int32_t * pAttr, uint32_t creatureKind)
{
	if (pAttr == NULL)
	{
		pAttr = m_attrs;
	}

	float value = 0;
	for (int i = C_POWER; i < (int)C_CHARACTER_PRO; ++i)
	{
		const AttributeAttributeCfgInfo * pConfig = g_GetAttributeAttributeCfgTable()->GetAttributeAttributeCfgInfo(i);
		if (pConfig && pConfig->vec_profForbid[m_attrs[P_PROF]-1] ==1)
		{
			if (creatureKind == CREATURE_PLAYER)
			{
				int32_t tmpAttr = pAttr[g_GetAttrMgr()->GetPAttr(i)];
				//减掉技能和buff所加属性，战斗力暂时不要加这些模块所加的属性
				if (i < (int)C_FIGHT_ATTR_END)
				{
					uint32_t cSkillNum = g_GetAttrMgr()->GetSKillCNumAttr(CREATURE_PLAYER, i);
					uint32_t cBuffNum = g_GetAttrMgr()->GetBuffCNumAttr(CREATURE_PLAYER, i);
					tmpAttr -= pAttr[GetAttrNum(cSkillNum)];
					tmpAttr -= pAttr[GetAttrNum(cBuffNum)];
				}

				value += tmpAttr * pConfig->powerAmend;
			}
			//else if (creatureKind == CREATURE_PET)
			//{
			//	value += pAttr[g_GetAttrMgr()->GetMAttr(i)] * pConfig->powerAmend;
			//}
		}
	}
	return value;
}

uint32_t Player::CalcPlayerFightPower(bool sync)
{
	m_attrs[P_FIGHT_POWER] = 0;
	float value = 0;
	value = CalcAttrFightPower();
	//再加上人物所有技能+人物宠物的技能
	SkillPart * pPart = dynamic_cast<SkillPart *>(m_pPart[PART_SKILL]);
	if (pPart)
	{
		value += pPart->GetAllSkillFightPower();
	}
	
	//只缓存，同步客户端在外层处理
	if (!sync)
	{
		SetAttrPACache(P_FIGHT_POWER, value);
	}
	else
		SetAttrPA(P_FIGHT_POWER, value, sync);

	return m_attrs[P_FIGHT_POWER];
}

bool Player::C2AttrPoint(const char* data, uint32_t nlen)
{

	const FunctionunlockFunctionUnlockCfgInfo * pConfig = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ADDPOINT);
	if (!pConfig || pConfig->unlockLevel>m_attrs[P_LEVEL])
	{
		LogDebugFmtPrint("C2AttrPoint level not enouth level=%d",m_attrs[P_LEVEL]);
		return false;
	}


	AttrAddPointResult rsp;
	AttrPoint playerAttrs;
	if (!playerAttrs.ParseFromArray(data, nlen))
		return false;
	int32_t Attrmax = playerAttrs.playerattrs_size();

	Attr attrCell;
	int32_t  aPoint = playerAttrs.apoint();
	int32_t  advancePoint = 0;
	for (int32_t i = 0; i < Attrmax; i++)
	{
		attrCell = playerAttrs.playerattrs(i);
		advancePoint += attrCell.attrvalue();
	}

	if (aPoint < 0 || aPoint != advancePoint || !CheckAttrValue(C_ATTR_POINT, aPoint))
	{
		
		rsp.set_result(RET_FAIL);
		SendDataToClient(LOGIC_TO_CLIENT_ADD_POING_RESULT, &rsp);
		return false;
	}

	AddAttrPACache(P_ATTR_POINT, -aPoint);
	for (int32_t i = 0; i < Attrmax; i++)
	{
		attrCell = playerAttrs.playerattrs(i);
		AddAttrPACache(attrCell.attrnum(), attrCell.attrvalue());
	}

	SynAttrToClient();

	rsp.set_result(RET_SUCCESS);
	SendDataToClient(LOGIC_TO_CLIENT_ADD_POING_RESULT, &rsp);

	AddPoingEvent addEvent;
	addEvent.point = aPoint;
	addEvent.charId = GetCid();
	g_GetEvent()->FireExecute(EVENT_ADD_ATT_POINT, m_Cid, CREATURE_PLAYER, (AddPoingEvent*)&addEvent, sizeof(AddPoingEvent));
	return true;
}
bool Player::C2AttrClearPoint(const char* data, uint32_t nlen)
{

	const FunctionunlockFunctionUnlockCfgInfo * pConfig = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ADDPOINT);
	if (!pConfig || pConfig->unlockLevel > m_attrs[P_LEVEL])
	{
		LogDebugFmtPrint("C2AttrPoint level not enouth level=%d", m_attrs[P_LEVEL]);
		return false;
	}

	AttrClearResult result;
	AttrPoint playerAttrs;
	if (!playerAttrs.ParseFromArray(data, nlen))
		return false;
	int32_t Attrmax = playerAttrs.playerattrs_size();

	Attr attrCell;
	int32_t aPoint = playerAttrs.apoint();
	int32_t  advancePoint = 0;
	for (int32_t i = 0; i < Attrmax; i++)
	{
		attrCell = playerAttrs.playerattrs(i);
		advancePoint = attrCell.attrvalue();
		if ((m_attrs[attrCell.attrnum()] - advancePoint) < 0)
			return false;
	}

	//判断金币够不够
	const ConstantConstantCfgInfo *pClearAttrCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Item);
	if (nullptr == pClearAttrCfg)
	{
		LogErrFmtPrint("[logic] Player::C2AttrClearPoint.....nullptr == pClearAttrCfg, id:%d ", EArg_ClearPoint_Item);
		return false;
	}


	//扣道具
	PackagePart * pPackPart = dynamic_cast<PackagePart*>(m_pPart[PART_PACKAGE]);
	SItemSourceParam soureParam;
	soureParam.source = S_ClearAttr;
	if (!pPackPart || !pPackPart->RemoveItem(pClearAttrCfg->constantdata, 1, soureParam))
	{
		result.set_result(RET_PACKAGE_ITEM_NOT_EXITS);
		SendDataToClient(LOGIC_TO_CLIENT_CLEAR_POINT_RESULT, &result);
		return false;
	}

	ClearPointEvent clearEvent;
	clearEvent.point = aPoint;
	g_GetEvent()->FireExecute(EVENT_CLEAR_POING, m_Cid, CREATURE_PLAYER, (ClearPointEvent*)&clearEvent, sizeof(ClearPointEvent));

	//AddAttrPACache(P_GOLD, -1 * pClearAttrCfg->constantdata*aPoint);

	AddAttrPACache(P_ATTR_POINT, aPoint);
	int32_t value = 0;
	for (int32_t i = 0; i < Attrmax; i++)
	{
		attrCell = playerAttrs.playerattrs(i);
		value = attrCell.attrvalue();
		AddAttrPACache(attrCell.attrnum(), -value);
	}

	SynAttrToClient();

	result.set_result(RET_SUCCESS);
	SendDataToClient(LOGIC_TO_CLIENT_CLEAR_POINT_RESULT, &result);

	return true;
}

bool Player::C2AutoAttrPoint(const char* data, uint32_t nlen)
{
	AutoAttrPoint autoAttr;
	if (!autoAttr.ParseFromArray(data, nlen))
		return false;
	if (autoAttr.setauto()>6)
	{
		return false;
	}
	SetAttrPACache(P_AUTO_ATTR_POINT, autoAttr.setauto());
	for (int i = 0; i < autoAttr.autoattrs_size(); i++)
		SetAttrPACache(autoAttr.autoattrs(i).attrnum(), autoAttr.autoattrs(i).attrvalue());

	SynAttrToClient();
	return true;
}
//玩家静态地图复活
bool  Player::C2RelivePlayer(const char* data, uint32_t nlen)
{
	PlayerReliveRequest msgReq;
	if (!msgReq.ParseFromArray(data, nlen))
		return false;

	if (m_curstate !=State_dead)
	{
		return false;
	}

	OnNearBornRevive();

	//if (msgReq.relivetype() == PlayerReliveRequest::enRelive_free)
	//{
	//	//新加需求，死亡复活先找他父地图，有直接复活在他父地图中
	//	uint32_t reliveMapId = m_mapId;
	//	const MapMapCfgInfo * pMapCfg = g_GetMapMapCfgTable()->GetMapMapCfgInfo(m_mapId);
	//	if (pMapCfg )
	//	{
	//		uint32_t tmpMap = CommonApi::StrToInt(pMapCfg->parentMap);
	//		if (tmpMap>0)
	//		{
	//			reliveMapId = tmpMap;
	//		}
	//	}
	//	//复活到该地图的复活点
	//	Point3<float> pos = g_GetMapLocationCfg()->GetNearRelivePos(reliveMapId, m_pos, m_attrs[P_CAMP_ID]);
	//	if (pos.length()<=0)
	//	{
	//		//直接找默认的地图复活
	//		const ConstantConstantCfgInfo *pConstCfg =g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_Relive_Default_MapID);
	//		if (pConstCfg)
	//		{
	//			pos = g_GetMapLocationCfg()->GetNearRelivePos(pConstCfg->constantdata, m_pos, m_attrs[P_CAMP_ID]);
	//			if (pos.length() <= 0)
	//			{
	//				//找不到复活点
	//				PlayerReliveResponse msgRsp;
	//				msgRsp.set_retcode(RET_RELIVE_POS_NOT_FIND);
	//				return SendDataToClient(LOGIC_TO_CLIENT_RELIVE_RESULT, &msgRsp);
	//			}
	//			else
	//			{
	//				MovePart * pPart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	//				if (pPart)
	//				{
	//					OnRevive(m_Cid);
	//					pPart->TransScene(pConstCfg->constantdata, pos, pConstCfg->constantdata);
	//				}
	//			}
	//		}
	//	}
	//	else
	//	{
	//		if (reliveMapId==m_mapId)
	//		{
	//			if (!Teleporting(pos))
	//			{
	//				PlayerReliveResponse msgRsp;
	//				msgRsp.set_retcode(RET_RELIVE_POS_NOT_FIND);
	//				return SendDataToClient(LOGIC_TO_CLIENT_RELIVE_RESULT, &msgRsp);
	//			}

	//			OnRevive(m_Cid);
	//		}
	//		else
	//		{
	//			MovePart * pPart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	//			if (pPart)
	//			{
	//				OnRevive(m_Cid);

	//				pPart->TransScene(reliveMapId, pos, reliveMapId);
	//			}
	//		}
	//		
	//	}
	//}
	//else  //扣钻石
	//{
	//	//先判断钻石是否够
	//	int32_t needDiamond = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg::EArg_Field_Relive_Money)->constantdata;
	//	if (m_attrs64[P_GOLD]<needDiamond)
	//	{
	//		PlayerReliveResponse msgRsp;
	//		msgRsp.set_retcode(RET_MONEY_LACK);
	//		return SendDataToClient(LOGIC_TO_CLIENT_RELIVE_RESULT, &msgRsp);
	//	}

	//	AddAttr(C_GOLD, -1 * (int64_t)needDiamond, true);
	//}

	PlayerReliveResponse msgRsp;
	msgRsp.set_retcode(RET_SUCCESS);
	SendDataToClient(LOGIC_TO_CLIENT_RELIVE_RESULT, &msgRsp);


	//去掉系统自动复活定时器
	g_GetTimerAxis()->KillTimer(enTime_Relive,this);

	return true;
}

bool Player::StartTalkToNpc(const char* data, uint32_t nlen) //开始同NPC讲话
{
	PlayerStartTalkToBattleNpc req;
	if (!req.ParseFromArray(data, nlen))
		return false;

	if (this->GetScene() == nullptr) return false;

	CharIDType npcCid = req.npc_cid();
	Npc* pNpc = dynamic_cast<Npc*>(GetScene()->GetCreature(npcCid));
	if (pNpc && pNpc->GetBattleInfo() != nullptr && pNpc->GetAiData())
	{
		pNpc->GetAiData()->SetAiEnable(false);
	}
	return true;
}

bool Player::StopTalkToNpc(const char* data, uint32_t nlen) //开始同NPC讲话
{
	PlayerStopTalkToBattleNpc req;
	if (!req.ParseFromArray(data, nlen))
		return false;

	if (this->GetScene() == nullptr) return false;

	CharIDType npcCid = req.npc_cid();
	Npc* pNpc = dynamic_cast<Npc*>(GetScene()->GetCreature(npcCid));
	if (pNpc && pNpc->GetBattleInfo() != nullptr && pNpc->GetAiData())
	{
		pNpc->GetAiData()->SetAiEnable(true);
	}
	return true;
}

bool Player::FetchMissionPrestige(const char* data, uint32_t nlen)//领取任务声望奖励
{
	FetchMissionPrestigeReq req;
	if (!req.ParseFromArray(data, nlen))
	{
		LogErrFmtPrint("FetchMissionPrestigeReq parse failed...");
		return false;
	}
	uint32_t fetchid = req.fetch_id();
	const FameFameCfgInfo *pFameCfg = g_GetFameFameCfgTable()->GetFameFameCfgInfo(fetchid);
	if (nullptr == pFameCfg)
	{
		LogErrFmtPrint("Player::FetchMissionPrestige..nullptr == pFameCfg...cid:%lu,fetchid:%u ",GetCid(),fetchid);
		return false;
	}
	FetchMissionPrestigeRsp rsp;
	SET_UINT32::iterator iter = m_setMissionPrestige.find(fetchid);
	if (iter != m_setMissionPrestige.end())
	{
		//已领取
		rsp.set_retcode(RET_PACKAGE_FETCHED_MISSION_PRESTIGE);
	}
	else if (GetAttr(C_MISSION_PRESTIGE) < pFameCfg->fameNeed)
	{
		//声望不足
		rsp.set_retcode(RET_PACKAGE_FETCHED_MISSION_PRESTIGE);
	}
	else
	{
		Part *pPackage = GetPart(PART_PACKAGE);
		if (nullptr == pPackage)
		{
			LogErrFmtPrint("Player::FetchMissionPrestige..nullptr == pPackage...cid:%lu,fetchid:%u ", GetCid(), fetchid);
			return false;
		}
		rsp.set_retcode(RET_SUCCESS);
		int32_t prof = GetAttr(C_PROF);
		VecFameFameFameCfg::const_iterator iter = pFameCfg->vecFameFameFameCfg.begin();
		for (; iter != pFameCfg->vecFameFameFameCfg.end(); ++iter)
		{
			const FameFameFameCfgInfo &info = (*iter);
			if (info.profession == prof)
			{
				SItemSourceParam sourceParam;
				sourceParam.source = S_MissionPrestige;
				if (pPackage->AddItem(info.reward, 1, sourceParam))
				{
					rsp.set_retcode(RET_SUCCESS);
					rsp.set_fetch_id(fetchid);
					m_setMissionPrestige.insert(fetchid);
				}
				else
				{
					rsp.set_retcode(RET_PACKAGE_SPACE_NOT_ENOUGH);
				}

				break;
			}
		}
	}
	SendDataToClient(LOGIC_TO_CLIENT_FETCH_MISSION_PRESTIGE, &rsp);

	return true;
}

bool Player::C2UseMonster(const char* data, uint32_t nlen)
{
	PlayerUseMonsterReq req;
	if (!req.ParseFromArray(data, nlen))
		return false;

	PlayerUseMonsterRep rep;
	CharIDType monsterCid = req.monstercid();
	Monster* pMonster = g_GetCreatureMgr()->GetMonster(monsterCid);
	if (pMonster)
	{
		if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_CAN_USE_THING)
		{
			auto pAiData = pMonster->GetAiData();
			if (pAiData)
			{
				SkillPart* pSkillPart = dynamic_cast<SkillPart*>(pMonster->GetPart(PART_SKILL));
				if (pSkillPart)
				{
					std::vector<uint32_t> vec;
					pSkillPart->GetMonsterCanUseSkillID(vec);
					if (vec.empty())
					{
						pSkillPart->GetNormalSkillID(vec);
					}

					if (!vec.empty())
					{
						rep.set_retcode(RET_SUCCESS);
						SendDataToClient(LOGIC_TO_CLIENT_USE_MONSTER, &rep);
						pMonster->SetMonsterMasterCID(m_Cid);
						pAiData->UseMonsterTriggerEnemy();
						pMonster->SetAttrMA(M_LAST_USE_MONSTER_TIME, (Time::Now().UnixSec()), true);
						pMonster->SynAttrToClient();

						UseMonsEvent useEvent;
						useEvent.monsId = pMonster->GetConfigId();
						g_GetEvent()->FireExecute(EVENT_PLAYER_USE_MONSTER, GetCid(), CreatureKind(), &useEvent, sizeof(useEvent));
						return true;
					}
				}
			}
		}
		else if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_CAN_USE_DROP)
		{
			rep.set_retcode(RET_SUCCESS);
			SendDataToClient(LOGIC_TO_CLIENT_USE_MONSTER, &rep);
			
			Point3<float> pos = pMonster->GetPos();
			g_GetDropMgr()->UseThingDrop(this, pMonster->GetConfigId(), (int32_t)pMonster->GetAttr(C_LEVEL), pos);
			pMonster->AddAttr(C_HP, -1, false);
			pMonster->SetAttrMA(M_LAST_USE_MONSTER_TIME, (Time::Now().UnixSec()), true);
			pMonster->SynAttrToClient();
			return true;
		}
	}

	rep.set_retcode(RET_FAIL);
	SendDataToClient(LOGIC_TO_CLIENT_USE_MONSTER, &rep);
	return true;
}

bool Player::C2SaveGuidelines(const char* data, uint32_t nlen) //保存新手指引
{
	GuidelinesSaveReq req;
	if (!req.ParseFromArray(data, nlen))
		return false;
	m_strGuidelines = req.strsave();
	return true;
}
bool Player::C2SavePlot(const char* data, uint32_t nlen)  //保存过场动画
{
	PlotSaveReq req;
	if (!req.ParseFromArray(data, nlen))
		return false;
	m_strPlot = req.strsave();
	return true;
}

bool Player::SynLoginInfo()
{
	
	PlayerClientInfo playerInfo;
	playerInfo.set_createtime(m_createTime);
	playerInfo.set_logintime(m_loginTime);
	playerInfo.set_playerid(m_Cid);
	playerInfo.set_groupid(m_zid);
	playerInfo.set_playername(m_name);
	playerInfo.set_mspeed(m_attrs[P_MSPEED]/1000.0f);
	playerInfo.set_curstate(m_curstate); 
	playerInfo.set_strguidelines(m_strGuidelines);
	playerInfo.set_strplot(m_strPlot);
	playerInfo.set_planeid(m_planeID);
	playerInfo.set_deadtime(m_deadIntervalTime);
	playerInfo.set_currenttime(Time::Now().UnixMSec());
	playerInfo.mutable_facade();
	CharFacadeProto *facade = playerInfo.mutable_facade();
	if (facade)
	{
		GetFacade(facade);
	}
	//已领取的任务声望奖励
	SET_UINT32::iterator iterFetch = m_setMissionPrestige.begin();
	for (; iterFetch != m_setMissionPrestige.end(); ++iterFetch)
	{
		playerInfo.add_fetch_mission_pretige((*iterFetch));
	}

	//其他部件客户端数据 这里统一改到 Player.cpp LoginGame接口中了
	for (size_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
			m_pPart[i]->SynOnLogin(playerInfo);
	}

	uint32_t i = P_ATTR_ULONG_END + 1;
	Attr *pAttr = nullptr;
	Attr64 *pAttr64 = nullptr;
	for (; i < P_CLIENT_END; i++)
	{
		pAttr = playerInfo.add_playerattrs();
		pAttr->set_attrnum(i);
		pAttr->set_attrvalue(m_attrs[i]);
	}

	i = P_ATTR_POINT_POWER;
	for (; i <= P_ATTR_POINT_PRECISION; i++)
	{
		pAttr = playerInfo.add_playerattrs();
		pAttr->set_attrnum(i);
		pAttr->set_attrvalue(m_attrs[i]);
	}

	i = P_AUTO_ATTR_POINT;
	for (; i <= P_AUTO_ATTR_PRECISION; i++)
	{
		pAttr = playerInfo.add_playerattrs();
		pAttr->set_attrnum(i);
		pAttr->set_attrvalue(m_attrs[i]);
	}

	i = P_NONE + 1;
	for (; i < P_ATTR_ULONG_END;++i)
	{
		pAttr64 = playerInfo.add_playerattrs64();
		pAttr64->set_attrnum(i);
		pAttr64->set_attrvalue(m_attrs64[i]);
	}

	if (State_dead != m_curstate)
	{
		m_curstate = State_normal;
	}

	playerInfo.set_mapid(m_mapId);
	playerInfo.set_posx(m_pos.x);
	playerInfo.set_posy(m_pos.y);
	playerInfo.set_posz(m_pos.z);

	playerInfo.set_curstate(State_normal); //如果这里发死亡状态 ，客户端会卡死，查不到原因，这里先这样子处理


	//SetCanBeSeenFlag(true);  

	//清空下同步属性缓存，因为在初始化其它部件的时候，可能会有属性设置广播属性，但是该属性值不是最新的
	m_attrsCache.clear();
	m_attrs64Cache.clear();


	ProtoBufBase *pbuf = &playerInfo;
	SendDataToClient(LOGIC_TO_CLIENT_PLAYERINFO, pbuf);


	//启内挂定时器，然后下发时间到客户端
	if (m_i64StartUseLeiGuaItem>0)
	{
		int64_t leftTime = m_iLeiGuaAllTime-(Time::Now().sec() - m_i64StartUseLeiGuaItem);
		if (leftTime>0)
		{
			g_GetTimerAxis()->SetTimer(enTime_LeiGua,leftTime*1000,this,1);
			SyncLeiGuaLeftTimeToClient(leftTime);
		}
		else
		{
			m_i64StartUseLeiGuaItem = 0;
			m_iLeiGuaAllTime = 0;
		}
	}

	//上线时，清空上次活动数据，在线玩家活动结束清空，非在线玩家，上线时清空
	if (Time::Now().UnixSec() - m_logoutTime >6 * 60 * 60)
	{
		ClearAnswerActiveData();
	}

	//清空玩家每日答题数据，处理在活动节束时，玩家不在线的时候的情况
	if (m_activeDailyData.answerlist_size()>0)
	{
		const ConstantConstantCfgInfo *pConstCfg = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ServerUpdateTime);
		if (nullptr != pConstCfg)
		{
			Date newData = Time::GetLocalDate();
			Date loginoutData = Time::GetLocalDate(m_logoutTime);
			if (newData.mday==loginoutData.mday)
			{
				//是同一天，刚好错过刷新点，则重新刷下
				if (newData.hour > pConstCfg->constantdata && loginoutData.hour < pConstCfg->constantdata)
				{
					ClearDailyAnswerActiveData();
				}
			}
			else
			{
				//不是同一天，上线在刷新点后面，则要重新刷下
				if (newData.hour > pConstCfg->constantdata)
				{
					ClearDailyAnswerActiveData();
				}
			}
			
		}
	}


	//同步坐骑
	HorsePart * pHorsePart = dynamic_cast<HorsePart*>(m_pPart[PART_HORSE]);
	if (pHorsePart)
	{
		pHorsePart->SendHourseInfo();
	}


	return true;
}

//加经验值
void Player::AddExp(uint32_t expNum,uint32_t baseExp , uint32_t otherExp )
{
	uint32_t oldLevel = GetAttr(C_LEVEL);

	AddAttrPACache(P_EXP,expNum);


	//策划要求，经验要分开显示，故这里加一条消息专用于显示
	if (expNum > 0)
	{
		if (otherExp == 0)
		{
			baseExp = expNum;
		}
		SyncExpToClient(baseExp, otherExp);
	}

	//如果到了开放阵营等级，没加阵营的，不让升级 ，只加经验
	const FunctionunlockFunctionUnlockCfgInfo * pOpenCamp = g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_CAMP);
	if (pOpenCamp && (int32_t)oldLevel >= pOpenCamp->unlockLevel && m_attrs[P_CAMP_ID]<=0)
	{
		LogDebugFmtPrint("no camp can not to level");
		return;
	}

	//计算是否升级
	while (m_attrs[P_EXP]>=m_attrs[P_EXPMAX])
	{
		//到了最高级，按策划要求，让其经验证处于最大经验值减一状态
		if (g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_Player_Level_Max) && 
			(m_attrs[P_LEVEL] >= g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_Player_Level_Max)->constantdata))
		{
			m_attrs[P_LEVEL] = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_Player_Level_Max)->constantdata;
			m_attrs[P_EXP] = m_attrs[P_EXPMAX] - 1;
			break;
		}

		AddAttrPACache(P_EXP, -1 * m_attrs[P_EXPMAX]);
		AddAttrPACache(P_LEVEL, 1);
		LevAttrs(true);
	}

	uint32_t nowLevel = GetAttr(C_LEVEL);
	if (oldLevel != nowLevel)
	{
		SyncToCenter(C_LEVEL);	
		//玩家升级同步客户端的数据都从这里打包
		CreaturesLevUp leveInfo;
		leveInfo.set_cid(m_Cid);
		leveInfo.set_level(m_attrs[P_LEVEL]);
		for (size_t i = 0; i < PART_MAX; i++)
		{
			if (m_pPart[i])
				m_pPart[i]->SynCreatureLevUp(leveInfo);
		}
		if (leveInfo.ByteSize() > 0)
			SendDataToClient(LOGIC_TO_CLIENT_CREATURE_LEVUP, &leveInfo);

	}
	//排行版要有用到，等级相同，用经验排序
	SyncToCenter(C_EXP);

	SynAttrToClient();
}

//设置队伍属性
void Player::SetTeamAttr(uint32_t teamId, uint32_t isLeader, bool bsync /*= false*/)
{
	//这个事件放到 更新玩家队伍信息到逻辑服 的消息那边
	/*if (teamId <= 0)
	{
		LeaveTeamEvent leaveEvent;
		leaveEvent.cid = m_Cid;
		leaveEvent.teamID = GetPAttrValue(P_TEAM_ID);
		g_GetEvent()->FireExecute(ENENT_LEAVE_TEAM, GetPAttrValue(P_TEAM_ID), CREATURE_PLAYER, (LeaveTeamEvent*)&leaveEvent, sizeof(LeaveTeamEvent));
	}*/

	SetAttr(C_TEAM_ID, teamId, false);
	SetAttr(C_TEAM_LEADER_ID, isLeader, bsync);
	//重置上次一同步的生命值
	m_lastHp = 0;
	m_isLastMove = false;
}

//同步属性到中心服
void Player::SyncToCenter(int32_t C_attrId)
{
	if (C_attrId <= C_NONE || C_attrId >= C_MAX)
	{
		return;
	}
	LogicToCenterCharSync notify;
	notify.set_charid(m_Cid);
	CharSyncAttr* attrSyn = notify.add_attrlist();
	attrSyn->set_attrid(C_attrId);
	attrSyn->set_attrval(GetAttr(C_attrId));
	if (C_HP == C_attrId)
	{
		CharSyncAttr* attrSynA = notify.add_attrlist();
		attrSynA->set_attrid(C_MAX_HP);
		attrSynA->set_attrval(GetAttr(C_MAX_HP));
	}
	else if (C_MP == C_attrId)
	{
		CharSyncAttr* attrSynB = notify.add_attrlist();
		attrSynB->set_attrid(C_MAX_MP);
		attrSynB->set_attrval(GetAttr(C_MAX_MP));
	}
	g_GetLogicService()->SendDataToCenter(EMODULE_ID_SERV_SYS, CENTER_SERVER_PROTOCOL_LOGIC_TO_CENTER_CHAR_ATTR_SYNC, &notify);
}

//更新工会属性
void Player::SetUnionAttr(uint32_t unionId, const string &strName, int32_t duty, int32_t level, int32_t icon, int32_t contri, int32_t officeLev, int32_t vaultLev, uint32_t homeScene, bool syn)
{
	SetAttr(C_UNION_ID, unionId);
	SetAttr(C_UNION_DUTY, duty);
	SetAttr(C_UNION_LEVEL, level);
	SetAttr(C_UNION_ICON, icon, syn);
	SetAttr(C_UNION_CONTRI, contri);
	SetAttr(C_UNION_OFFICE_LEVEL, officeLev);
	SetAttr(C_UNION_VAULT_LEVEL, vaultLev);
	SetAttr(C_UNION_HOME_SCENE, homeScene);

	m_unionName = strName;
}
//获取工会名字
const string &Player::UnionName()
{
	return m_unionName;
}

//设置房间属性
void Player::SetRoomAttr(uint32_t roomId, int32_t isOwner)
{
	SetAttr(C_ROOM_ID, roomId);
	SetAttr(C_ROOM_LEADER_ID, isOwner);
}

//完成新手引导副本步骤
void Player::FinishGuideDupStep(uint32_t step)
{
	m_guideDup.set_finish_step(step);
}
//完成新手引导副本
void Player::FinshAllGuideStep()
{
	m_guideDup.set_finish_flag(1);
}
//是否已经完成新手引导副本
bool Player::IsFinishGuideDup()
{
	return m_guideDup.finish_flag();
}

//同步互客户端玩家非buff状态
void Player::UpdateStateToClient()
{
	CreatureUpdateState Sendmsg;
	//这里暂时只发一个战斗状态，后续有状态可以加这里
	if (m_isFightState)
	{
		Sendmsg.set_isfightstate(CreatureUpdateState::enState::CreatureUpdateState_enState_en_Yes);
	}
	else
	{
		Sendmsg.set_isfightstate(CreatureUpdateState::enState::CreatureUpdateState_enState_en_Not);
	}

	SendDataToClient(LOGIC_TO_CLIENT_UPATE_STATE, &Sendmsg);
}

void Player::InitLevAttrs()
{
	//if (m_logoutTime > 0)
	//{
	//	LevAttrs(false);
	//}
	//else
	//{
	//	//第一次登陆
	//	m_attrs[P_LEVEL] = 1;
	//	LevAttrs();
	//}
	LevAttrs(false);
}

bool Player::LevAttrs(bool levUp /* = true */)
{
	const RoleMasterCfgInfo *pMagicInfo = nullptr;
	const RoleShooterCfgInfo *pShooterInfo = nullptr;
	const RoleWarriorCfgInfo *pWarriorInfo = nullptr;
	const RoleAssassinCfgInfo *pAssassinInfo = nullptr;
	uint32_t i = 0;
	uint32_t t = 0;
	uint32_t apoint = 0;

	//算该等级的基础属性
	switch (m_attrs[P_PROF])
	{
	case ECHARACTER_PROF_WARRIOR:
		pWarriorInfo = g_GetRoleWarriorCfgTable()->GetRoleWarriorCfgInfo(m_attrs[P_LEVEL]);
		if (!pWarriorInfo)
		{
			LogErrFmtPrint("warrior lev cfg error");
			return false;
		}
		for (i = 0; i < pWarriorInfo->vecRoleWarriorAttributeCfg.size(); i++)
		{
			t = g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, pWarriorInfo->vecRoleWarriorAttributeCfg[i].Type);
			SetAttrPACache(t, pWarriorInfo->vecRoleWarriorAttributeCfg[i].Value);
		}
		apoint = pWarriorInfo->upgradePoint;
		
		break;
	case ECHARACTER_PROF_ASSASSIN:
		pAssassinInfo = g_GetRoleAssassinCfgTable()->GetRoleAssassinCfgInfo(m_attrs[P_LEVEL]);
		if (!pAssassinInfo)
		{
			LogErrFmtPrint("passassin lev cfg error");
			return false;
		}
		for (i = 0; i < pAssassinInfo->vecRoleAssassinAttributeCfg.size(); i++)
		{
			t = g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, pAssassinInfo->vecRoleAssassinAttributeCfg[i].Type);
			SetAttrPACache(t, pAssassinInfo->vecRoleAssassinAttributeCfg[i].Value);
		}
		apoint = pAssassinInfo->upgradePoint;
		break;
	case ECHARACTER_PROF_MAGICIAN:
		pMagicInfo = g_GetRoleMasterCfgTable()->GetRoleMasterCfgInfo(m_attrs[P_LEVEL]);
		if (!pMagicInfo)
		{
			LogErrFmtPrint("warrior type size != value size");
			return false;
		}
		for (i = 0; i < pMagicInfo->vecRoleMasterAttributeCfg.size(); i++)
		{
			t = g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, pMagicInfo->vecRoleMasterAttributeCfg[i].Type);
			SetAttrPACache(t, pMagicInfo->vecRoleMasterAttributeCfg[i].Value);
		}
		apoint = pMagicInfo->upgradePoint;
		break;
	case ECHARACTER_PROF_ARCHER:
		pShooterInfo = g_GetRoleShooterCfgTable()->GetRoleShooterCfgInfo(m_attrs[P_LEVEL]);
		if (!pShooterInfo)
		{
			LogErrFmtPrint("warrior type size != value size");
			return false;
		}
		for (i = 0; i < pShooterInfo->vecRoleShooterAttributeCfg.size(); i++)
		{
			t = g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, pShooterInfo->vecRoleShooterAttributeCfg[i].Type);
			SetAttrPACache(t, pShooterInfo->vecRoleShooterAttributeCfg[i].Value);
		}
		apoint = pShooterInfo->upgradePoint;
		break;
	default:
		break;
	}


	//算最大经验和体力
	const RoleExpCfgInfo *pcfg = g_GetRoleExpCfgTable()->GetRoleExpCfgInfo(m_attrs[P_LEVEL]);
	if (!pcfg)
	{
		LogErrFmtPrint("expcfg wrong!");
		return false;
	}
	SetAttrPACache(P_EXPMAX, pcfg->exp);
	SetAttrPACache(P_MAX_STAMINA, pcfg->stamina);
	
	//计算回血值
	const RoleBornCfgInfo *pRoleBornCfg = g_GetRoleBornCfg((uint8_t)m_attrs[P_PROF], (uint8_t)m_attrs[P_GENDER]);
	if (!pRoleBornCfg)
	{
		LogErrFmtPrint("Player::LevAttrs pRoleBornCfg  ==null prof=%d,gender=%d", m_attrs[P_PROF], m_attrs[P_GENDER]);
		return false;
	}
		std::vector<float> vHp;
		std::vector<float> vMp;
		CommonApi::SplitStrToVecFloat(pRoleBornCfg->restoreHp, ",", &vHp);
		CommonApi::SplitStrToVecFloat(pRoleBornCfg->restoreMp, ",", &vMp);
		if ((int)vHp.size() != 3 || (int)vMp.size() != 3)
		{
			LogErrFmtPrint("restore hp mp config param wrong!!!!!");
			return false;
		}

		//公式为 level*level*a+level*b+c
		uint32_t nHp = m_attrs[P_LEVEL] * m_attrs[P_LEVEL] * vHp[0] + m_attrs[P_LEVEL] * vHp[1] + vHp[2];
		uint32_t nMp = m_attrs[P_LEVEL] * m_attrs[P_LEVEL] * vMp[0] + m_attrs[P_LEVEL] * vMp[1] + vMp[2];

		SetAttrPACache(g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, C_RESTORE_HP), nHp);
		SetAttrPACache(g_GetAttrMgr()->GetPlayerFightModlePAttr(enFightAttrModule_Level, C_RESTORE_MP), nMp);
	

	//如果等于1，则重新置下自动加点属性，大于最大等级，清空自动加点属性
	if (m_attrs[P_LEVEL] == 1 && m_attrs[P_EXP] == 0)
	{
		if (GetPAttrValue(C_AUTO_ATTR_POWER) > 0 || GetPAttrValue(C_AUTO_ATTR_INTELLIGENCE) > 0
			|| GetPAttrValue(C_AUTO_ATTR_AGILITY) > 0 || GetPAttrValue(C_AUTO_ATTR_PHYSIQUE) > 0
			|| GetPAttrValue(C_AUTO_ATTR_ENDURANCE) > 0 || GetPAttrValue(C_AUTO_ATTR_PRECISION) > 0)
		{
			//有设置过，表示不是新号
		}
		else
		{
			levUp = true; //新号第一次进来，也走升级到1级流程，统一处理

			std::vector<int32_t> vPoint;
			CommonApi::SplitStrToVecInt(pRoleBornCfg->addPoint, ",", &vPoint);
			if ((int)vPoint.size() >= 6)
			{
				SetAttr(C_AUTO_ATTR_POWER, vPoint[0]);
				SetAttr(C_AUTO_ATTR_INTELLIGENCE, vPoint[1]);
				SetAttr(C_AUTO_ATTR_AGILITY, vPoint[2]);
				SetAttr(C_AUTO_ATTR_PHYSIQUE, vPoint[3]);
				SetAttr(C_AUTO_ATTR_ENDURANCE, vPoint[4]);
				SetAttr(C_AUTO_ATTR_PRECISION, vPoint[5]);
			}
			else
			{
				LogDebugFmtPrint("auto add point config error prof=%d,gender=%d", m_attrs[P_PROF], m_attrs[P_GENDER]);
			}
		}
	}
	else if (levUp && g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ADDPOINT) &&
		m_attrs[P_LEVEL] == g_GetFunctionunlockFunctionUnlockCfgTable()->GetFunctionunlockFunctionUnlockCfgInfo(FunctionUnlock_ID_TYPE_ADDPOINT)->unlockLevel + 1)
	{
			
			
		//清空自动加点
		SetAttr(C_AUTO_ATTR_POWER, 0);
		SetAttr(C_AUTO_ATTR_INTELLIGENCE, 0);
		SetAttr(C_AUTO_ATTR_AGILITY, 0);
		SetAttr(C_AUTO_ATTR_PHYSIQUE, 0);
		SetAttr(C_AUTO_ATTR_ENDURANCE, 0);
		SetAttr(C_AUTO_ATTR_PRECISION, 0);
	}
	
	//升级加点，且发送升级事件
	if (levUp)
	{
		AddAttrPACache(P_ATTR_POINT, apoint);

		uint32_t autopointpower = GetAttr(C_AUTO_ATTR_POWER);
		uint32_t autopointt = GetAttr(C_AUTO_ATTR_INTELLIGENCE);
		uint32_t autopointagility = GetAttr(C_AUTO_ATTR_AGILITY);
		uint32_t autopointphysique = GetAttr(C_AUTO_ATTR_PHYSIQUE);
		uint32_t autopointendurance = GetAttr(C_AUTO_ATTR_ENDURANCE);
		uint32_t autopointprecision = GetAttr(C_AUTO_ATTR_PRECISION);
		if (autopointpower>0)
		{
			AddAttrPACache(P_ATTR_POINT_POWER, autopointpower);
		}
		if (autopointt>0)
		{
			AddAttrPACache(P_ATTR_POINT_INTELLIGENCE, autopointt);
		}
		if (autopointagility>0)
		{
			AddAttrPACache(P_ATTR_POINT_AGILITY, autopointagility);
		}
		if (autopointphysique>0)
		{
			AddAttrPACache(P_ATTR_POINT_PHYSIQUE, autopointphysique);
		}
		if (autopointendurance>0)
		{
			AddAttrPACache(P_ATTR_POINT_ENDURANCE, autopointendurance);
		}
		if (autopointprecision>0)
		{
			AddAttrPACache(P_ATTR_POINT_PRECISION, autopointprecision);
		}
		AddAttrPACache(P_ATTR_POINT, -1 * (autopointpower + autopointt + autopointagility + autopointphysique + autopointendurance + autopointprecision));

		//发送玩家升级事件
		//攻击事件触发
		PlayerLeveUpEvent  levelupInfo;
		levelupInfo.cid = m_Cid;
		levelupInfo.level = m_attrs[P_LEVEL];
		g_GetEvent()->FireExecute(EVENT_LEVELUP, m_Cid, CreatureKind(), (PlayerLeveUpEvent*)&levelupInfo, sizeof(PlayerLeveUpEvent));

		//玩家升级流水日志
		LevUpLog();
	}
	return true;
}

bool Player::ReadBaseData(CharacterDBInfo &PlayerInfo)
{
	m_Cid = PlayerInfo.charid();
	m_zid = PlayerInfo.groupid();
	
	//m_channelId = PlayerInfo.basedata().channelid();
	//m_userid = PlayerInfo.basedata().userid();
	//m_userName = PlayerInfo.basedata().username();

	m_createTime = PlayerInfo.basedata().createtime();
	//最后一次保存时间，每次重新登录或者切换逻辑节点之后，需要修改为当前时间
	//避免玩家下线之后，长时间不登录，再次登录的时候 玩家数据会立刻保存一次 (定时保存会根据这个时间来做判断)
	//m_lastSaveTime = PlayerInfo.basedata().lastsavetime();
	m_lastSaveTime = g_GetGlobalServerTime()->UnixSec();
	//
	m_onlineTime = PlayerInfo.basedata().onlinetime();
	m_logoutTime = PlayerInfo.basedata().logouttime();
	m_loginTime = PlayerInfo.basedata().logintime();

	m_name = PlayerInfo.basedata().name();
	m_attrs[P_GENDER] = PlayerInfo.basedata().sex();
	m_attrs[P_PROF] = PlayerInfo.basedata().prof();
	m_attrs[P_LEVEL] = PlayerInfo.basedata().level();
	m_attrs[P_EXP] = (int32_t)PlayerInfo.basedata().exp();
	m_attrs[P_HP] = PlayerInfo.basedata().hp();
	m_attrs[P_MP] = PlayerInfo.basedata().mp();
	m_attrs[P_FIGHT_POWER] = PlayerInfo.basedata().fightpower();
	m_attrs64[P_GOLD] = PlayerInfo.basedata().gold();
	m_attrs[P_GOLD_BIND] = PlayerInfo.basedata().bindgold();
	m_attrs[P_DIAMOND] = PlayerInfo.basedata().diamond();
	m_attrs[P_DIAMOND_BIND] = PlayerInfo.basedata().binddiamond();

	m_attrs[P_STAMINA] = PlayerInfo.basedata().stamina();

	m_dir.x = PlayerInfo.basedata().dirx();
	m_dir.y = PlayerInfo.basedata().diry();
	m_dir.z = PlayerInfo.basedata().dirz();

	//m_attrs[P_POWER]		= PlayerInfo.basedata().power();
	//m_attrs[P_INTELLIGENCE] = PlayerInfo.basedata().intelligence();
	//m_attrs[P_AGILITY]		= PlayerInfo.basedata().agility();
	//m_attrs[P_PHYSIQUE]		= PlayerInfo.basedata().physique();
	//m_attrs[P_ENDURANCE]	= PlayerInfo.basedata().endurance();
	//m_attrs[P_PRECISION]	= PlayerInfo.basedata().precision();

	SetAttrPACache(P_ATTR_POINT_POWER, PlayerInfo.basedata().pointpower());
	SetAttrPACache(P_ATTR_POINT_INTELLIGENCE, PlayerInfo.basedata().pointintelligence());
	SetAttrPACache(P_ATTR_POINT_AGILITY, PlayerInfo.basedata().pointagility());
	SetAttrPACache(P_ATTR_POINT_PHYSIQUE, PlayerInfo.basedata().pointphysique());
	SetAttrPACache(P_ATTR_POINT_ENDURANCE, PlayerInfo.basedata().pointendurance());
	SetAttrPACache(P_ATTR_POINT_PRECISION, PlayerInfo.basedata().pointprecision());

	m_attrs[P_AUTO_ATTR_POINT]		       = PlayerInfo.basedata().autopoint();
	m_attrs[P_AUTO_ATTR_POWER] = PlayerInfo.basedata().autopower();
	m_attrs[P_AUTO_ATTR_INTELLIGENCE] = PlayerInfo.basedata().autointelligence();
	m_attrs[P_AUTO_ATTR_AGILITY] = PlayerInfo.basedata().autoagility();
	m_attrs[P_AUTO_ATTR_PHYSIQUE] = PlayerInfo.basedata().autophysique();
	m_attrs[P_AUTO_ATTR_ENDURANCE] = PlayerInfo.basedata().autoendurance();
	m_attrs[P_AUTO_ATTR_PRECISION] = PlayerInfo.basedata().autoprecision();

	m_attrs[P_ATTR_POINT] = PlayerInfo.basedata().attr_point();
	m_attrs[P_ENERGY] = PlayerInfo.basedata().energy();

	m_sceneId = PlayerInfo.basedata().enter_scene_id();
	m_mapId = PlayerInfo.basedata().enter_map_id();
	m_pos.x = PlayerInfo.basedata().enterposx();
	m_pos.y = PlayerInfo.basedata().enterposy();
	m_pos.z = PlayerInfo.basedata().enterposz();
	m_attrs[P_DUPLICATE_ID] = PlayerInfo.basedata().duplicate_id();
	m_attrs[P_CAMP_ID] = PlayerInfo.basedata().camp();
	m_attrs[P_OFFICIAL] = PlayerInfo.basedata().official();
	m_attrs[P_KNIGHT] = PlayerInfo.basedata().knight();
	m_attrs[P_CAMP_SCORE] = PlayerInfo.basedata().contribute();
	m_attrs[P_CAMP_COIN] = PlayerInfo.basedata().contricoin();
	m_attrs[P_CAMP_PRESTIGE] = PlayerInfo.basedata().prestige();
	m_attrs[P_CAMP_KILLERS] = PlayerInfo.basedata().killers();
	m_attrs[P_RACE] = PlayerInfo.basedata().race();
	m_attrs[P_ARENA_SCORE] = PlayerInfo.basedata().arenascore();
	m_attrs[P_CHARM] = PlayerInfo.basedata().charm();
	m_attrs[P_CAMP_HIS_PRESTIGE] = PlayerInfo.basedata().hisprestige();
	m_curstate = PlayerInfo.basedata().curstate();
	m_deadIntervalTime = PlayerInfo.basedata().lastrevivetime();

	//任务声望
	m_attrs[P_MISSION_PRESTIGE] = 0;
	m_setMissionPrestige.clear();
	if (PlayerInfo.basedata().has_mission_prestige())
	{
		const CharacterDBMissionPrestige &protoPrestige = PlayerInfo.basedata().mission_prestige();
		m_attrs[P_MISSION_PRESTIGE] = protoPrestige.prestige();
		int32_t isize = protoPrestige.fetch_size();
		for (int32_t i = 0; i < isize; ++i)
		{
			m_setMissionPrestige.insert(protoPrestige.fetch(i));
		}
	}
	if (PlayerInfo.basedata().has_guide_dup())
	{
		m_guideDup.CopyFrom(PlayerInfo.basedata().guide_dup());
	}

	m_attrClient.set_cid(m_Cid);
	m_attrBroadcastClient.set_cid(m_Cid);
	m_lastMapId = PlayerInfo.basedata().lastmapid();
	m_lastSceneId = PlayerInfo.basedata().lastsceneid();
	m_lastPos.x = PlayerInfo.basedata().lastposx();
	m_lastPos.y = PlayerInfo.basedata().lastposy();
	m_lastPos.z = PlayerInfo.basedata().lastposz();

	//这个以后数据库表改了再改先这样
	//string userid = PlayerInfo.basedata().userid();
	//m_uid = std::atoi(userid.c_str());

	//竞技场数据
	m_arenaData.CopyFrom(PlayerInfo.arenadata());

	m_attrs[P_USE_TITLE]	 = PlayerInfo.basedata().usetitle();
	m_attrs[P_ADDATTR_TITLE] = PlayerInfo.basedata().addattrtitle();

	if (PlayerInfo.basedata().has_strguidelines())
	{
		m_strGuidelines = PlayerInfo.basedata().strguidelines();
	}

	if (PlayerInfo.basedata().has_strplot())
	{
		m_strPlot = PlayerInfo.basedata().strplot();
	}

	//m_planeID = PlayerInfo.basedata().planeid();

	//如果位面不存在，则看接清除该值,有可能是服务器半闭时，该玩家已下线，且有位面信息
	//if (!g_GetPlaneMgr()->IsInPlane(m_planeID,m_Cid))
	//{
	//	m_planeID = 0;
	//}

	//填充补偿信息
	m_buChanInfo.clear();
	for (int32_t i = 0; i < PlayerInfo.basedata().buchaninfo_size(); i++)
	{
		m_buChanInfo.push_back(PlayerInfo.basedata().buchaninfo(i));
	}

	m_attrs[P_ARENA_STRAIGHT] = PlayerInfo.basedata().arenastraight();
	

	m_i64StartUseLeiGuaItem = PlayerInfo.basedata().startuseleiguatime();
	m_iLeiGuaAllTime = PlayerInfo.basedata().leiguaalltime();

	m_activeData.CopyFrom(PlayerInfo.playeractiveinfo().playeractiveanswerinfo());
	m_activeDailyData.CopyFrom(PlayerInfo.playeractiveinfo().playeractivedailyanswerinfo());

	return true;
}

void Player::SetAccountInfo(CharLoginInfo* pLoginInfo)
{
	if (NULL == pLoginInfo)
	{
		LogErrFmtPrint("Player::SetAccountInfo, pLoginInfo == null, cid:", m_Cid);
		return;
	}
	m_clientId = pLoginInfo->clientId;
	m_uid = pLoginInfo->uid;
	m_gateId = pLoginInfo->gateId;
	m_chanId = pLoginInfo->channelId;
}

void Player::GetVisibleDataToClient(CreaturesCreateData& cvData)
{
	CreaturesCreateData::Player *pPlayerVinfo = cvData.add_players();
	if (nullptr == pPlayerVinfo)
	{
		return;
	}
	pPlayerVinfo->set_playerid(m_Cid);
	pPlayerVinfo->set_level(m_attrs[P_LEVEL]);
	pPlayerVinfo->set_playername(m_name);
	pPlayerVinfo->set_hp(m_attrs[P_HP]);
	pPlayerVinfo->set_maxhp(m_attrs[P_MAX_HP]);
	pPlayerVinfo->set_posx(m_pos.x);
	pPlayerVinfo->set_posy(m_pos.y);
	pPlayerVinfo->set_posz(m_pos.z);
	pPlayerVinfo->set_prof(m_attrs[P_PROF]);
	pPlayerVinfo->set_gender(m_attrs[P_GENDER]);
	pPlayerVinfo->set_playerrace(m_attrs[P_RACE]);
	pPlayerVinfo->set_curstate(m_curstate);
	pPlayerVinfo->set_mspeed(m_attrs[P_MSPEED]*1.0/1000);
	pPlayerVinfo->set_pk_mode(GetPkMode());
	pPlayerVinfo->set_pk_killing_value(GetPkKillingValue());
	pPlayerVinfo->set_team_id(m_attrs[P_TEAM_ID]);
	pPlayerVinfo->set_is_leader(m_attrs[P_TEAM_LEADER_ID]);
	pPlayerVinfo->set_camp_id(m_attrs[P_CAMP_ID]);
	pPlayerVinfo->set_union_id(m_attrs[P_UNION_ID]);
	pPlayerVinfo->set_union_icon(m_attrs[P_UNION_ICON]);
	pPlayerVinfo->set_unionname(m_unionName);
	pPlayerVinfo->set_titleid(m_attrs[P_USE_TITLE]);
	pPlayerVinfo->set_fightvalue(m_attrs[P_FIGHT_POWER]);
	pPlayerVinfo->set_sonofkillingtime(m_attrs[P_SONOFKILLING_TIME]);
	pPlayerVinfo->set_curseoffalltime(m_attrs[P_CURSE_OF_FALL]);

	GetFacade(pPlayerVinfo->mutable_facade());

	MovePart * pPart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	if (pPart)
	{
		ActorMove actormove;
		ActorRockerMove rockmove;
		pPart->GetMoveingState(actormove, rockmove);
		if (pPart->GetMoveFlag() == enMovingFlag_Mouse)
		{
			ActorMove *pActormove = pPlayerVinfo->mutable_actormove();
			pActormove->CopyFrom(actormove);
		}
		else if (pPart->GetMoveFlag() == enMovingFlag_Rock)
		{
			ActorRockerMove * pRockMove = pPlayerVinfo->mutable_rockmove();
			pRockMove->CopyFrom(rockmove);
		}
	}

	CollectPart *pCollectPart = dynamic_cast<CollectPart*>(m_pPart[PART_COLLECT]);
	if (pCollectPart)
	{
		CollectData *pCollectData = pPlayerVinfo->mutable_collect_data();
		//pCollectData->set_cid(m_Cid);
		pCollectData->set_collect_type(pCollectPart->GetCollecType());
	}

	BuffPart * pBuffPart = dynamic_cast<BuffPart*>(m_pPart[PART_BUFF]);
	if (pBuffPart)
	{
		msgBuffList * pList = pPlayerVinfo->mutable_bufflist();
		pBuffPart->GetAllBuffInfo(pList);
	}

}

void Player::SynAttrToClient()
{
	if (m_curstate == State_Init)
		return;
	FinallyCalcChangeAttr();
	if (m_bIsNeedCalcFight)
	{
		//发送计算事件
		CalcFightPowerEvent calcFightPower;
		calcFightPower.cid = m_Cid;
		g_GetEvent()->FireExecute(EVENT_CALC_FIGHT_POWER, m_Cid, CREATURE_PLAYER, (CalcFightPowerEvent*)&calcFightPower, sizeof(CalcFightPowerEvent));

		m_bIsNeedCalcFight = false;
	}

	SynAttr();
	Creature::SynAttrToClient();
}

//------------------------------------------------------------------------------------------------------
CharIDType Player::GetId() { return m_Cid; }

void Player::SetAccountState(AccountGameState state)
{
	m_accountState = state; 
	//这里将这两个状态分开，是因为中心服发这两个状态是两条不同的消息
	//第一条是收到断线立马发 ACCOUNT_GAME_STATE_DISCONNECT
	//第二条是检测时间到了，发下线，这里也分开处理。。。。 modify by wangxx
	if (ACCOUNT_GAME_STATE_DISCONNECT == state) //下线了
	{
		OperateWelfarePart* pOperatePart = dynamic_cast<OperateWelfarePart*>(m_pPart[PART_WELFARE]);
		if (pOperatePart)
		{
			pOperatePart->Offline();
		}

		SetCanBeSeenFlag(false);
		MovePart * pMovePart = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
		if (pMovePart)  //下线停止移动
		{
			pMovePart->StopSelfMove();
		}
		UpdateSeeLst();

		m_logoutTime = Time::Now().UnixSec();

		m_onlineTime += m_logoutTime - m_loginTime;

		////即时存一次盘
		_DoSave(true);

	}
	else if (ACCOUNT_GAME_STATE_LOGOUT == state)
	{
		_DoSave(true);
		////做一下离开场景操作
		LeaveScene();
	}
	else if (state == ACCOUNT_GAME_STATE_GAMING) //移到收到客户端发来进入场景完成了再置这个标记
	{
		//SetCanBeSeenFlag(true);
	}
	else if (state == ACCOUNT_GAME_STATE_SWITCH)
	{
		SetCanBeSeenFlag(false);
	}
}

AccountGameState Player::GetAccountState()
{
	return m_accountState;
}

HostNode* Player::GetHostNode() { return &m_hostNode; }

uint64_t Player::GetLastSaveTime() { return m_lastSaveTime; }

uint64_t Player::GetLogoutTime() { return m_logoutTime; }

uint64_t Player::GetOnlineSec() { return m_onlineTime; }

uint64_t Player::GetLoginTime() { return m_loginTime; }

bool Player::Logout(LOGOUT_TYPE type /*= LOGOUT_TYPE_NONE*/)
{
	bool result = false;

	//MMOLOG_ASSERT_EXIT(!m_leaveGameSave);
	//这里logout时，已经是玩家正式下线后30分钟了，
	//m_logoutTime = ServerTime::UnixSec();

	if (LOGOUT_TYPE_CHANGE_LOGIC != type) //切场景不能发下线事件
	{
		for (uint32_t i = PART_NONE + 1; i < PART_MAX; i++)
		{
			if (m_pPart[i])
				m_pPart[i]->SynLogout();
		}

		//下线事件(处理下线逻辑,要放在保存之前，有可能对数据有修改并且需要保存）
		LoginOutGame logoutEvent;
		logoutEvent.cid = GetCid();
		logoutEvent.uid = GetUid();
		g_GetEvent()->FireExecute(EVENT_LOGINOUT_GAME, GetCid(), CreatureKind(), &logoutEvent, sizeof(logoutEvent));

		//玩家下线日志
		LoginOutLog();
	}

	//TriggerSave(true); 去掉此处代码 因为在SetAccountState会做一次存档操作了 fix by lian
	//LeaveScene();
	result = true;
	
	//如果有位面，则销毁位面
	if (m_planeID>0)
	{
		g_GetPlaneMgr()->LeavePlane(m_Cid);
	}

	//切换逻辑服之后,玩家数据在发送到目标逻辑服了之前会保存一次数据，
	//源逻辑服在这之后改变的玩家数据都不能该保存,
	if (LOGOUT_TYPE_CHANGE_LOGIC != type)  											
	{
		SetAccountState(ACCOUNT_GAME_STATE_LOGOUT);
	}
	else
	{
		//切换逻辑服成功之后，在源逻辑服需要离开场景
		LeaveScene();
	}
	


	return result;
}
bool Player::ChangeLogic()
{
	//这里需要设置下下线时间,现在游戏 是否是第一次进入游戏是通过这个时间来判断的（用于第一次进入游戏的一些奖励，初始化处理），
	//如果切换逻辑节点不设置下线时间，切换到逻辑节点之后会在执行一次第一次进入游戏的初始化处理（第一次进入游戏初始物品）
	//切换逻辑节点不能设置为下线时间 要不会导致其他用到下线时间的系统有bug
	//m_logoutTime = g_GetGlobalServerTime()->UnixSec();
	//设置为切逻辑服状态
	SetAccountState(ACCOUNT_GAME_STATE_SWITCH);
	SetCanBeSeenFlag(false);
	if (GetPlaneID() > 0)
	{
		g_GetPlaneMgr()->LeavePlane(GetCid());
	}
	return _DoSave(true);
}


// @direct：是否立即存储到DB，或者通过update错开帧去存储
bool Player::TriggerSave(bool direct /* = false */)
{
	return _DoSave(direct);
}

bool Player::_DoSave(bool direct /* = false */)
{
	bool result = false;
	bool retCode = false;
	uint64_t requestId = g_GetLogicService()->GetDBRequestCount();
	CharacterInfoUpdateRequest reqPack;
	CharacterDBInfo* charInfo = NULL;
	uint64_t old_saveTime = m_lastSaveTime;

	//LogDebugFmtPrint("[logic] Player::_DoSave...charid:%llu , direct:%d ",m_Cid,(int32_t)direct);
	if (!direct)
	{
		MMO_PROCESS_FALSE(ServerTime::UnixSec() < (m_lastSaveTime + s_saveSpaceTime));
	}
	MMO_PROCESS_ERROR(g_GetLogicService()->IsConnectDBProxy());

	reqPack.set_groupid(m_zid);
	reqPack.set_requestid(requestId);
	reqPack.set_uid(m_uid);

	charInfo = reqPack.mutable_charinfo();
	MMOLOG_ASSERT_EXIT(charInfo != NULL);
	
	m_lastSaveTime = ServerTime::UnixSec();//先在这里设置上次保存时间，如果失败的话，在设置为 old_saveTime
	retCode = GetSaveDBData(*charInfo);
	MMOLOG_ASSERT_EXIT(retCode);



	retCode = g_GetLogicService()->SendDataToDBProxy(EMODULE_ID_PLAYER,DBPROXY_PROTOCOL_SET_CHARACTER_DATA_REQ, &reqPack);
	MMOLOG_PROCESS_ERROR(retCode);


	//LogDebugFmtPrint("save hp=%d",m_attrs[P_HP]);

	//LogDebugFmtPrint("[logic] Player::_DoSave....db save...charid:%llu ",m_Cid );
	
	result = true;

Exit0:
	if (!result)
	{
		m_lastSaveTime = old_saveTime;
	}
	return result;
}

bool Player::GetSaveDBData(CharacterDBInfo& charInfo)
{
	PROFILE_SEGMENT("Player::GetSaveDBData");
	return _Serialize(charInfo);
}

void Player::GetSellItems(PlayerSellBackItem& sellItem)
{
	PackagePart *part = dynamic_cast<PackagePart*>(GetPart(PART_PACKAGE));
	if (nullptr != part)
	{
		part->GetSellItems(sellItem);
	}
}

void Player::SetSellItems(const PlayerSellBackItem& sellItem)
{
	PackagePart *part = dynamic_cast<PackagePart*>(GetPart(PART_PACKAGE));
	if (nullptr != part)
	{
		part->SetSellItems(sellItem);
	}
}

bool Player::_Serialize(CharacterDBInfo& charInfo)
{
	bool result = false;
	bool retCode = true;
	CharacterDBActiveInfo* pInfo = nullptr;
	charInfo.set_charid(GetId());
	charInfo.set_groupid(GetZid());

	retCode = _SaveCharacterBaseData(charInfo);
	MMOLOG_PROCESS_ERROR(retCode);

	for (uint32_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
		{
			retCode = m_pPart[i]->SaveDB(charInfo);
			MMOLOG_PROCESS_ERROR(retCode);
		}
	}
	_SaveCharacterExtraData(charInfo);
	_SaveCharacterArenaData(charInfo);

	pInfo = charInfo.mutable_playeractiveinfo();
	if (pInfo)
	{
		pInfo->mutable_playeractiveanswerinfo()->CopyFrom(m_activeData);
		pInfo->mutable_playeractivedailyanswerinfo()->CopyFrom(m_activeDailyData);
	}

	result = true;
Exit0:
	return result;
}
bool Player::_SaveCharacterBaseData(CharacterDBInfo& charInfo)
{
	char setStr[64];
	memset(setStr, 64, 0);
	snprintf(setStr, 64, "%d", m_uid);

	CharacterDBBaseInfo* charBaseInfo = charInfo.mutable_basedata();
	//charBaseInfo->set_channelid(GetChannelId());
	//charBaseInfo->set_userid(setStr);
	//charBaseInfo->set_username(GetChannelUserName());
	charBaseInfo->set_createtime(m_createTime);
	charBaseInfo->set_lastsavetime(m_lastSaveTime);
	charBaseInfo->set_onlinetime(m_onlineTime);
	charBaseInfo->set_logintime(m_loginTime);
	charBaseInfo->set_logouttime(m_logoutTime);

	charBaseInfo->set_name(m_name);
	charBaseInfo->set_sex(m_attrs[P_GENDER]);
	charBaseInfo->set_prof(m_attrs[P_PROF]);
	charBaseInfo->set_level(m_attrs[P_LEVEL]);
	charBaseInfo->set_exp(m_attrs[P_EXP]);
	charBaseInfo->set_mp(m_attrs[P_MP]);
	charBaseInfo->set_hp(m_attrs[P_HP]);
	charBaseInfo->set_fightpower(m_attrs[P_FIGHT_POWER]);
	charBaseInfo->set_gold(m_attrs64[P_GOLD]);
	charBaseInfo->set_bindgold(m_attrs[P_GOLD_BIND]);
	charBaseInfo->set_diamond(m_attrs[P_DIAMOND]);
	charBaseInfo->set_binddiamond(m_attrs[P_DIAMOND_BIND]);
	charBaseInfo->set_enter_scene_id(m_sceneId);
	charBaseInfo->set_enter_map_id(m_mapId);
	charBaseInfo->set_enterposx(m_pos.x);
	charBaseInfo->set_enterposy(m_pos.y);
	charBaseInfo->set_enterposz(m_pos.z);
	charBaseInfo->set_lastmapid(m_lastMapId);
	charBaseInfo->set_lastsceneid(m_lastSceneId);
	charBaseInfo->set_lastposx(m_lastPos.x);
	charBaseInfo->set_lastposy(m_lastPos.y);
	charBaseInfo->set_lastposz(m_lastPos.z);

	charBaseInfo->set_duplicate_id(m_attrs[P_DUPLICATE_ID]);
	charBaseInfo->set_camp(m_attrs[P_CAMP_ID]);
	charBaseInfo->set_official(m_attrs[P_OFFICIAL]);
	charBaseInfo->set_knight(m_attrs[P_KNIGHT]);
	charBaseInfo->set_contribute(m_attrs[P_CAMP_SCORE]);
	charBaseInfo->set_contricoin(m_attrs[P_CAMP_COIN]);
	charBaseInfo->set_prestige(m_attrs[P_CAMP_PRESTIGE]);
	charBaseInfo->set_killers(m_attrs[P_CAMP_KILLERS]);
	charBaseInfo->set_race(m_attrs[P_RACE]);
	charBaseInfo->set_curstate(m_curstate);
	charBaseInfo->set_lastrevivetime(m_deadIntervalTime);
	charBaseInfo->set_stamina(m_attrs[P_STAMINA]);	
	charBaseInfo->set_charm(m_attrs[P_CHARM]);
	charBaseInfo->set_hisprestige(m_attrs[P_CAMP_HIS_PRESTIGE]);

	charBaseInfo->set_power(m_attrs[P_POWER]);
	charBaseInfo->set_intelligence(m_attrs[P_INTELLIGENCE]);
	charBaseInfo->set_agility(m_attrs[P_AGILITY]);
	charBaseInfo->set_physique(m_attrs[P_PHYSIQUE]);
	charBaseInfo->set_endurance(m_attrs[P_ENDURANCE]);
	charBaseInfo->set_precision(m_attrs[P_PRECISION]);

	charBaseInfo->set_pointpower(m_attrs[P_ATTR_POINT_POWER]);
	charBaseInfo->set_pointintelligence(m_attrs[P_ATTR_POINT_INTELLIGENCE]);
	charBaseInfo->set_pointagility(m_attrs[P_ATTR_POINT_AGILITY]);
	charBaseInfo->set_pointphysique(m_attrs[P_ATTR_POINT_PHYSIQUE]);
	charBaseInfo->set_pointendurance(m_attrs[P_ATTR_POINT_ENDURANCE]);
	charBaseInfo->set_pointprecision(m_attrs[P_ATTR_POINT_PRECISION]);

	charBaseInfo->set_autopoint(m_attrs[P_AUTO_ATTR_POINT]);
	charBaseInfo->set_autopower(m_attrs[P_AUTO_ATTR_POWER]);
	charBaseInfo->set_autointelligence(m_attrs[P_AUTO_ATTR_INTELLIGENCE]);
	charBaseInfo->set_autoagility(m_attrs[P_AUTO_ATTR_AGILITY]);
	charBaseInfo->set_autophysique(m_attrs[P_AUTO_ATTR_PHYSIQUE]);
	charBaseInfo->set_autoendurance(m_attrs[P_AUTO_ATTR_ENDURANCE]);
	charBaseInfo->set_autoprecision(m_attrs[P_AUTO_ATTR_PRECISION]);
	charBaseInfo->set_attr_point(m_attrs[P_ATTR_POINT]);
	charBaseInfo->set_energy(m_attrs[P_ENERGY]);
	charBaseInfo->set_usetitle(m_attrs[P_USE_TITLE]);
	charBaseInfo->set_addattrtitle(m_attrs[P_ADDATTR_TITLE]);
	charBaseInfo->set_arenascore(m_attrs[P_ARENA_SCORE]);
	charBaseInfo->set_strguidelines(m_strGuidelines);
	charBaseInfo->set_strplot(m_strPlot);
	//charBaseInfo->set_sonofkillingtime(m_attrs[P_SONOFKILLING_TIME]);

	//charBaseInfo->set_planeid(m_planeID);

	charBaseInfo->set_dirx(m_dir.x);
	charBaseInfo->set_diry(m_dir.y);
	charBaseInfo->set_dirz(m_dir.z);
	charBaseInfo->set_arenastraight(m_attrs[P_ARENA_STRAIGHT]);

	charBaseInfo->clear_buchaninfo();
	for (uint32_t i = 0; i < m_buChanInfo.size(); i++)
	{
		charBaseInfo->add_buchaninfo(m_buChanInfo[i]);
	}
	//
	charBaseInfo->set_startuseleiguatime(m_i64StartUseLeiGuaItem);
	charBaseInfo->set_leiguaalltime(m_iLeiGuaAllTime);
	//
	CharacterDBMissionPrestige *protoPrestige = charBaseInfo->mutable_mission_prestige();
	if (nullptr != protoPrestige)
	{
		protoPrestige->set_prestige(m_attrs[P_MISSION_PRESTIGE]);
		SET_UINT32::iterator iter = m_setMissionPrestige.begin();
		for (; iter != m_setMissionPrestige.end(); ++iter)
		{
			protoPrestige->add_fetch((*iter));
		}
	}
	//
	CharacterDBGuideDupInfo *protoGuideDup = charBaseInfo->mutable_guide_dup();
	if (nullptr != protoGuideDup)
	{
		protoGuideDup->CopyFrom(m_guideDup);
	}

	return true;
}

bool Player::_SaveCharacterExtraData(CharacterDBInfo& charInfo)
{
	CharacterDBExtendData *pextra = charInfo.mutable_extenddata();
	if (nullptr == pextra)
	{
		MMOLOG_FMT_ERROR("[logic] nullptr == pextra....charInfo.mutable_extenddata failed....");
		return false;
	}
	CharacterDBAttrDetailInfo *pattr = pextra->mutable_attr_detail();
	_SetCharacterDetailAttr(pattr);

	return true;
}
void Player::_SetCharacterDetailAttr(CharacterDBAttrDetailInfo *pattr)
{
	if (nullptr == pattr)
	{
		return;
	}
	pattr->set_max_hp(m_attrs[P_MAX_HP]);
	pattr->set_intelligence(m_attrs[P_INTELLIGENCE]);
	pattr->set_agility(m_attrs[P_AGILITY]);
	pattr->set_physique(m_attrs[P_PHYSIQUE]);
	pattr->set_endurance(m_attrs[P_ENDURANCE]);
	pattr->set_precision(m_attrs[P_PRECISION]);
	pattr->set_max_mp(m_attrs[P_MAX_MP]);
	pattr->set_ap(m_attrs[P_AP]);
	pattr->set_mat(m_attrs[P_MAT]);
	pattr->set_dp(m_attrs[P_DP]);
	pattr->set_mdp(m_attrs[P_MDP]);
	pattr->set_phyhit(m_attrs[P_PHYHIT]);
	pattr->set_phydodge(m_attrs[P_PHYDODGE]);
	pattr->set_phycrit(m_attrs[P_PHYCRIT]);
	pattr->set_magcrit(m_attrs[P_MAGCRIT]);
	pattr->set_phytoughness(m_attrs[P_PHYTOUGHNESS]);
	pattr->set_magtoughness(m_attrs[P_MAGTOUGHNESS]);
	pattr->set_phycritmul(m_attrs[P_PHYCRITMUL]);
	pattr->set_magcritmul(m_attrs[P_MAGCRITMUL]);
	pattr->set_fireatt(m_attrs[P_FIREATT]);
	pattr->set_firedef(m_attrs[P_FIREDEF]);
	pattr->set_icedatt(m_attrs[P_ICEATT]);
	pattr->set_iceddef(m_attrs[P_ICEDEF]);
	pattr->set_windatt(m_attrs[P_WINDATT]);
	pattr->set_winddef(m_attrs[P_WINDDEF]);
	pattr->set_solatt(m_attrs[P_SOLATT]);
	pattr->set_soldef(m_attrs[P_SOLDEF]);
	pattr->set_rayatt(m_attrs[P_RAYATT]);
	pattr->set_raydef(m_attrs[P_RAYDEF]);
	pattr->set_poisonatt(m_attrs[P_POISONATT]);
	pattr->set_poisondef(m_attrs[P_POISONDEF]);
	pattr->set_phycritextra(m_attrs[P_PHYCRITEXTRA]);
	pattr->set_phycritreduce(m_attrs[P_PHYCRITREDUCE]);
	pattr->set_phyextradamage(m_attrs[P_PHYEXTRADAMAGE]);
	pattr->set_phyreducedamage(m_attrs[P_PHYREDUCEDAMAGE]);
	pattr->set_magcritextra(m_attrs[P_MAGCRITEXTRA]);
	pattr->set_magcritreduce(m_attrs[P_MAGCRITREDUCE]);
	pattr->set_magextradamage(m_attrs[P_MAGEXTRADAMAGE]);
	pattr->set_magreducedamage(m_attrs[P_MAGREDUCEDAMAGE]);
	pattr->set_controldawn(m_attrs[P_CONTROLDAWN]);
	pattr->set_persistdown(m_attrs[P_PERSISTDOWN]);
	pattr->set_weakdown(m_attrs[P_WEAKDOWN]);
	pattr->set_displacedown(m_attrs[P_DISPLACEDOWN]);
	pattr->set_silencedown(m_attrs[P_SILENCEDOWN]);
	pattr->set_controlup(m_attrs[P_CONTROLUP]);
	pattr->set_persistup(m_attrs[P_PERSISTUP]);
	pattr->set_weakup(m_attrs[P_WEAKUP]);
	pattr->set_displaceup(m_attrs[P_DISPLACEUP]);
	pattr->set_silenceup(m_attrs[P_SILENCEUP]);
	pattr->set_cur_hp(m_attrs[P_HP]);
	pattr->set_magdodge(m_attrs[P_MAGDODGE]);
	pattr->set_maghit(m_attrs[P_MAGHIT]);

	Vector3PB *protoPos = pattr->mutable_cur_pos();
	if (nullptr != protoPos)
	{
		protoPos->set_x(m_pos.x);
		protoPos->set_y(m_pos.y);
		protoPos->set_z(m_pos.z);
	}
}

bool Player::_SaveCharacterArenaData(CharacterDBInfo& charInfo)
{
	charInfo.mutable_arenadata()->CopyFrom(m_arenaData);

	return true;
}

bool Player::CenterCharacterPack(CenterCharacterInfo* centerPackage)
{
	bool result = false;
	CharacterDBSimpleInfo* charSimpleInfo;
	centerPackage->set_scene_id(m_sceneId);
	centerPackage->set_map_id(m_mapId);
	charSimpleInfo = centerPackage->mutable_charsimpleinfo();
	charSimpleInfo->set_charid(GetId());
	charSimpleInfo->set_name(GetName());
	charSimpleInfo->set_sex(m_attrs[P_GENDER]);
	charSimpleInfo->set_prof(m_attrs[P_PROF]);
	charSimpleInfo->set_level(m_attrs[P_LEVEL]);
	charSimpleInfo->set_race(m_attrs[P_RACE]);
	charSimpleInfo->set_exp(m_attrs[P_EXP]);
	charSimpleInfo->set_hp(m_attrs[P_HP]);
	charSimpleInfo->set_fightpower(m_attrs[P_FIGHT_POWER]);
	charSimpleInfo->set_official(m_attrs[P_OFFICIAL]);
	charSimpleInfo->set_knight(m_attrs[P_KNIGHT]);
	charSimpleInfo->set_camp(m_attrs[P_CAMP_ID]);
	charSimpleInfo->set_contribute(m_attrs[P_CAMP_SCORE]);
	charSimpleInfo->set_contricoin(m_attrs[P_CAMP_COIN]);
	charSimpleInfo->set_prestige(m_attrs[P_CAMP_PRESTIGE]);
	charSimpleInfo->set_killers(m_attrs[P_CAMP_KILLERS]);
	charSimpleInfo->set_charm(m_attrs[P_CHARM]);
	charSimpleInfo->set_hisprestige(m_attrs[P_CAMP_HIS_PRESTIGE]);
	
	//详细属性
	CharacterDBAttrDetailInfo *protoAttr = centerPackage->mutable_attr();
	if (nullptr != protoAttr)
		_SetCharacterDetailAttr(protoAttr);
	else
		MMOLOG_FMT_ERROR("[logic] Player::CenterCharacterPack nullptr == protoAttr... enterReq.mutable_attr() failed....");

	//装备信息
	PackagePart *part = dynamic_cast<PackagePart*>(GetPart(PART_PACKAGE));
	if (nullptr == part)
	{
		MMOLOG_FMT_ERROR("[logic] Player::CenterCharacterPack nullptr == part...  failed....");
		return false;
	}
	
	VEC_PLAYER_EQUIP *pVecEquip = part->GetPlayerEquip();
	if (nullptr != pVecEquip)
	{
		VEC_PLAYER_EQUIP::iterator iterEquip = pVecEquip->begin();
		for (; iterEquip != pVecEquip->end(); ++iterEquip)
		{
			CItemBase *pEquip = (*iterEquip);
			if (nullptr == pEquip)
				continue;
			
			ItemProtoInfo *protoEquip = centerPackage->add_equip();
			if (nullptr == protoEquip)
			{
				MMOLOG_FMT_ERROR("[logic] Player::CenterCharacterPack nullptr == protoEquip... enterReqcenterPackage->add_equip() failed....");
				continue;
			}
			g_GetItemMgr()->SetItemProtoInfo(pEquip, protoEquip);
		}
	}

	//外观信息
	CharFacadeProto *facade = charSimpleInfo->mutable_facade();
	if (nullptr != facade)
		part->GetFacade(*facade);
	else
		MMOLOG_FMT_ERROR("[logic] Player::CenterCharacterPack nullptr == facade... enterReq.mutable_facade() failed....");


	result = true;
//Exit0:
	return result;
}

bool Player::TransScene(uint32_t scenceId, Point3<float>& dstPos, uint32_t mapId, STransParam &transParam)
{
	if (!m_pPart[PART_MOVE])
		return false;
	MovePart *pMove = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	return pMove->TransScene(scenceId, dstPos, mapId, transParam);
}

void Player::StopMove()
{
	if (!m_pPart[PART_MOVE])
		return;
	MovePart *pMove = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	return pMove->StopMove();
}

bool Player::MoveTo(Point3<float> dstPos)
{
	if (!m_pPart[PART_MOVE])
		return true;
	MovePart *pMove = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	return pMove->MoveTo(dstPos);
}

//瞬间移动
bool Player::Teleporting(Point3<float> dstPos)
{
	if (!m_pPart[PART_MOVE])
		return false;
	MovePart *pMove = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	return pMove->Teleporting(dstPos);
}

//被击退
bool Player::BeatBack(Point3<float> dstPos)
{
	if (!m_pPart[PART_MOVE])
		return false;
	MovePart *pMove = dynamic_cast<MovePart*>(m_pPart[PART_MOVE]);
	return pMove->BeatBack(dstPos);
}

//bool Player::AddStateBag(uint32_t skillid, uint32_t lev, ProtoBuf::BuffBagDetailInfo* pClientStatebag, Creature* pTarget /* = nullptr */)
//{
//	SkillPart *pSkillPart = dynamic_cast<SkillPart*>(m_pPart[PART_SKILL]);
//	if (!pSkillPart)
//		return false;
//
//	return pSkillPart->AddStateBag(skillid, lev, pClientStatebag, pTarget);
//}

bool Player::LeaveScene()
{
	Scene* pScene = m_pScene;
	if (Creature::LeaveScene())
	{
		if (pScene && pScene->GetAllPlayerInScene()->empty())
			g_GetEvent()->FireExecute(EVENT_SCENE_NO_PLAYER, pScene->GetSceneId(), 0, nullptr, 0);

		//summon leave scene
		g_GetCreatureMgr()->MasterLeaveScene(this);
		return true;
	}
	return false;
}

bool Player::EnterScene(uint32_t sceneId, Point3<float>& enterPos, STransParam &transParam)
{
	if (m_pScene)
	{
		if (m_pScene->GetSceneId() == sceneId)
			return false;
		if (!m_pScene->LeaveScene(m_Cid, m_pMyGrid))
			return false;
	}

	//LogAlwaysFmtPrint ("Player::EnterScene pScene is null, dstSceneId:%d cid:%llu, (x:%f, y:%f, z:%f)", sceneId, m_Cid, enterPos.x, enterPos.y, enterPos.z);

	m_pScene = g_GetSceneMgr()->GetScene(sceneId);
	if (!m_pScene)
	{
		LogErrFmtPrint("Player::EnterScene pScene is null, dstSceneId:%d cid:%lu, (x:%f, y:%f, z:%f),transtype:%d ", sceneId, m_Cid, enterPos.x, enterPos.y, enterPos.z, transParam.transType);
		return false;
	}

	m_pMyGrid = m_pScene->EnterScene(m_Cid, enterPos, this, transParam);
	if (!m_pMyGrid)
		return false;

	if (!m_pScene->IsDynamic())
	{
		if (m_lastMapId != m_pScene->GetMapId())
		{
			//当前场景不是动态场景，并且和上一个地图不是同一个地图
			LogDebugFmtPrint("[logic] Player::EnterScene...set last pos .....cid:%lu ,lastsceneid:%u ,lastmapid:%u,lastpos:%f,%f,%f,transtype:%d ", m_Cid, m_lastSceneId, m_lastMapId, m_lastPos.x, m_lastPos.y, m_lastPos.z,transParam.transType);
			m_lastPos = enterPos;
			m_lastSceneId = m_pScene->GetSceneId();
			m_lastMapId = m_pScene->GetMapId();
		}
	}
	else if (g_GetMapCfgMgr()->IsUnionHomeMap(m_mapId)
		|| g_GetMapCfgMgr()->IsUnionDunGeonMap(m_mapId)
		) //从工会场景或者工会地宫 跳到其他场景时需要 设置上一个场景为工会场景
	{
		//从公会地图或者工会地宫 进副本，退出副本之后还需要回到工会或者工会地宫地图，需要设置上一个地图为工会地图
		LogDebugFmtPrint("[logic] Player::EnterScene...union map trans to other map , set last pos .....cid:%lu ,lastsceneid:%u ,lastmapid:%u,lastpos:%f,%f,%f ,transtype:%d ", m_Cid, m_lastSceneId, m_lastMapId, m_lastPos.x, m_lastPos.y, m_lastPos.z,transParam.transType);
		m_lastPos = m_pos;
		m_lastSceneId = m_sceneId;
		m_lastMapId = m_mapId;
	}
	else if (!g_GetMapCfgMgr()->IsDynamic(m_mapId))
	{
		//目标场景是动态场景,当前场景如果是静态场景的话，把上次的场景设置为当前的场景
		LogDebugFmtPrint("[logic] Player::EnterScene... , set last scene parameter .....cid:%lu ,sceneid:%u ,mapid:%u,pos:%f,%f,%f ,transtype:%d ", m_Cid, m_sceneId, m_mapId, m_pos.x, m_pos.y, m_pos.z,transParam.transType);
		m_lastPos = m_pos;
		m_lastSceneId = m_sceneId;
		m_lastMapId = m_mapId;
	}

	m_pos = enterPos;
	m_sceneId = sceneId;
	m_mapId = m_pScene->GetMapId();


	//如果进的是流放之地，强制改模式
	const ConstantConstantCfgInfo *pJailMapID = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Jail);
	if ( pJailMapID)
	{
		if (pJailMapID->constantdata == (int32_t)m_sceneId)
		{
			PvpPart * pPvpPart = dynamic_cast<PvpPart*>(m_pPart[PART_PVP]);
			if (pPvpPart)
			{
				pPvpPart->SetPkMode((uint32_t)PK_MODE_KILLER);
			}
		}
	}
	
	//auto SeeIter = m_seeLst.begin();
	//for (; SeeIter != m_seeLst.end(); SeeIter++)
	//{
	//	//通知对方离开了我的视野
	//	Creature *pCreature = m_pScene->GetCreature(*SeeIter);
	//	if (pCreature)
	//		pCreature->DelSeeLst(this);
	//		//pCreature->DelBeenSeeLst(m_Cid);
	//}

//	m_seeLst.clear();
//	m_beenSeeLst.clear();
//	m_nineList.clear();
	UpdateNineGridLst();

	LogDebugFmtPrint("[logic] Player::EnterScene...set cure pos .....cid:%lu ,cursceneid:%u ,curmapid:%u,curpos:%f,%f,%f ,curHp=%d,MaxHp=%d,transtype:%d ", m_Cid, m_sceneId, m_mapId, m_pos.x, m_pos.y, m_pos.z, m_attrs[P_HP], m_attrs[P_MAX_HP],transParam.transType);

	//summon enter scene
	//g_GetCreatureMgr()->MasterEneterScene(this, sceneId, enterPos);

	if (m_pScene && m_pScene->GetAllPlayerInScene()->size() == 1)
		g_GetEvent()->FireExecute(EVENT_SCENE_FIRST_PLAYER, m_pScene->GetSceneId(), 0, nullptr, 0);
	return true;
}

bool Player::ForceReturnLastPlace()
{
	if (!m_pPart[PART_MOVE])
		return false;
	MovePart *pMove = (MovePart*)(m_pPart[PART_MOVE]);
	if (nullptr == pMove)
	{
		return false;
	}
	STransParam transParam;
	transParam.srcMapId = GetMapId();
	transParam.transType = ETransType_Scene;
	return pMove->TransScene(m_lastSceneId, m_lastPos, m_lastMapId, transParam);
}

//获取外观
void Player::GetFacade(CharFacadeProto *facade)
{
	PackagePart *pPart = dynamic_cast<PackagePart*>(GetPart(PART_PACKAGE));
	if (pPart)
	{
		pPart->GetFacade(*facade);
	}

	HorsePart* pHorsePart = dynamic_cast<HorsePart*>(GetPart(PART_HORSE));
	if (pHorsePart)
	{
		facade->set_cur_horse_id(pHorsePart->GetCurHorseId());
	}
}

// 分帧任务处理函数
// 返回值，任务是否完成
bool Player::DoTask(TaskNodeId type, void* data, uint32_t size)
{
	switch (type)
	{
	case TNID_SAVE_DB:
		{
			 _DoSave();
		}
	case TNID_SYNC_HP_CENTER:
		{
			SyncToCenter(C_HP);
		}
	default:
		{
		}
	}

	return true;
}

bool Player::HasBuffStateBag(uint32_t stateBagId)
{
	Part* pPart = GetPart(PART_BUFF);
	if (pPart)
	{
		return pPart->BuffEffect_HasBuffBag(stateBagId);
	}
	return false;
}

void Player::BuffEffect_ReduceDamage(Creature* pAttack, uint32_t skillId, int32_t &damage){
	if (HasBuffStateReduceDamage())
	{
		Part* pPart = GetPart(PART_BUFF);
		if (pPart)
		{
			return pPart->BuffEffect_ReduceDamage(pAttack, skillId, damage);
		}
	}
}

void Player::BuffEffect_AddExtraDamage(Creature* pBeAttacked, uint32_t skillId, int32_t &damage)
{
	if (HasBuffStateAddExtraDamage())
	{
		Part* pPart = GetPart(PART_BUFF);
		if (pPart)
		{
			return pPart->BuffEffect_AddExtraDamage(pBeAttacked, skillId, damage);
		}
	}
}

void Player::BuffEffect_CleanupAllFadeOutEffects(BuffInfoEndType endType)
{
	BuffPart* pBuffPart = static_cast<BuffPart*>(GetPart(PART_BUFF));
	if (pBuffPart)
	{
		pBuffPart->BuffEffect_CleanupAllFadeOutEffects(endType);
	}
}
bool Player::LoginInGame(CharLoginInfo& loginInfo, bool change /* = false */)
{
	if (nullptr == g_GetSceneMgr()->GetScene(loginInfo.sceneid))
	{
		LogErrFmtPrint("[logic] Player::LoginInGame.... cid:%llu,uid:%u, sceneid:%u, mapid:%u, change:%d ",m_Cid,m_uid,loginInfo.sceneid, loginInfo.mapid,(int32_t)change );
		return false;
	}
	Point3<float> enterpos(loginInfo.x, loginInfo.y, loginInfo.z);
	//先设置坐标和场景
	m_sceneId = loginInfo.sceneid;
	m_mapId = loginInfo.mapid;
	m_pos = enterpos;
	//这里需要设置下clientId

	m_clientId = loginInfo.clientId;
	m_gateId = loginInfo.gateId;
	m_chanId = loginInfo.channelId;
	m_uid = loginInfo.uid;

	IDuplicate *pDuplicate = g_GetDuplicateMgr()->GetDuplicate(loginInfo.sceneid);
	if (nullptr == pDuplicate || (int8_t)EDuplicateType::EDuplicateType_UnionHome == pDuplicate->GetType())
	{
		m_attrs[P_DUPLICATE_ID] = 0;
	}
	//有时间人物会在空中，这里上线，直接重新找下合适的点吧..todo
	Map * pMap=g_GetMapMgr()->GetMap(m_mapId);
	if (nullptr != pMap)
	{
		pMap->FindNearestPos(m_pos.x,m_pos.z,m_pos.y,&m_pos.x,&m_pos.z,&m_pos.y,NULL);
	}
	//处理中心服玩家相关的数据
	OnCharCenterData(loginInfo.protoLogin);
	
	//登录如果是死亡状态，直接复活
	if (m_curstate == State_dead)
	{
		OnRevive(m_Cid);
	}
	//设置游戏状态,需要再切换场景前面，切换场景中可能会涉及到跨逻辑节点需要修改状态的
	SetAccountState(ACCOUNT_GAME_STATE_GAMING);
	if (!TransScene(m_sceneId, m_pos, m_mapId, loginInfo.transParam))
	{
		LogErrFmtPrint("[logic] Player::LoginInGame....player TransScene failed.. cid:%llu, sceneid:%u, mapid:%u,pos:[%f,%f,%f],dstscene:%u,dstmap:%u,dstpos:%f,%f,%f, change:%d ",
			m_Cid, loginInfo.sceneid, loginInfo.mapid, enterpos.x, enterpos.y, enterpos.z,m_sceneId,m_mapId,m_pos.x,m_pos.y,m_pos.z, change);
		return false;
	}
	//
	//判断竞技场次数刷新
	uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
	if (TimeUtility::CheckDayUpdate(curTime, m_arenaData.updatetime()))
	{
		m_arenaData.set_challengetimes(0);
		m_arenaData.set_updatetime(curTime);
	}
	//
	if (!change)//不是切场景才能发送登录事件
	{
		for (size_t i = 0; i < PART_MAX; i++)
		{
			if (m_pPart[i])
				m_pPart[i]->SynOnLogin();
		}
		//设置本次登录时间,这个设置需要放到 各个部件回调 SynOnLogin 接口之后，各个部件需要上次登录时间做一些判断
		m_loginTime = curTime;
		//登录事件
		LoginGame login;
		login.cid = m_Cid;
		login.uid = m_uid;
		g_GetEvent()->FireExecute(EVENT_LOGIN_GAME, m_Cid, m_creatureKind, &login, sizeof(LoginGame));
		LoginLog(); //玩家登陆日志同步到logserver

	}
	else
	{
		OnChangeLogic();
		SetSellItems(loginInfo.sellItem);
	}

	//m_bBeenSee = false;

	return true;
}

//切换逻辑节点成功的处理
void Player::OnChangeLogic()
{
	//切换逻辑节点，部件的处理
	for (size_t i = 0; i < PART_MAX; i++)
	{
		if (nullptr != m_pPart[i])
		{
			m_pPart[i]->OnChangeLogic();
		}			
	}

	OnChangeLogicSynAttr();

	//同步下战斗状态标记
	UpdateStateToClient();

	//启内挂定时器，然后下发时间到客户端
	if (m_i64StartUseLeiGuaItem > 0)
	{
		int64_t leftTime = m_iLeiGuaAllTime - (Time::Now().sec() - m_i64StartUseLeiGuaItem);
		if (leftTime > 0)
		{
			g_GetTimerAxis()->SetTimer(enTime_LeiGua, leftTime * 1000, this, 1);
		}
		else
		{
			m_i64StartUseLeiGuaItem = 0;
			m_iLeiGuaAllTime = 0;
		}
	}
}

//同步中心服玩家相关的属性
void Player::OnCharCenterData(CharLoginSyncCenterData &protoSync)
{
	//工会
	SetUnionAttr(protoSync.union_id(), protoSync.union_name(), protoSync.uinon_duty(), protoSync.union_level(), protoSync.union_icon(), protoSync.union_contri(), protoSync.office_level(), protoSync.vault_level(), protoSync.union_home_scene(), false);
	//组队
	SetTeamAttr(protoSync.team_id(), protoSync.is_leader(), false);
	//房间
	SetRoomAttr(protoSync.room_id(), protoSync.is_owner());

	//
	LogInfoFmtPrint("OnCharCenterData...cid:%lu,unionid:%u,u_name:%s,duty:%d,u_level:%d,u_icon:%d,contri:%d,officelev:%d,vaultlev:%d,homescene:%u,teamid:%d,isleader:%d,roomid:%d,isowner:%d ", GetCid(), protoSync.union_id(), protoSync.union_name().c_str(), protoSync.uinon_duty(), protoSync.union_level(), protoSync.union_icon(), protoSync.union_contri(), protoSync.office_level(), protoSync.vault_level(), protoSync.union_home_scene(), protoSync.team_id(), (int32_t)protoSync.is_leader(), protoSync.room_id(), (int32_t)protoSync.is_owner());
}

//切逻辑节点同步基础属性
void Player::OnChangeLogicSynAttr()
{
	//同步玩家基本属性
	uint32_t i = P_ATTR_ULONG_END + 1;
	for (; i < P_CLIENT_END; i++)
	{
		SynAttrCache(i);
	}

	i = P_ATTR_POINT_POWER;
	for (; i <= P_ATTR_POINT_PRECISION; i++)
	{
		SynAttrCache(i);
	}

	i = P_AUTO_ATTR_POINT;
	for (; i <= P_AUTO_ATTR_PRECISION; i++)
	{
		SynAttrCache(i);
	}

	i = P_NONE + 1;
	for (; i < P_ATTR_ULONG_END; ++i)
	{
		SynAttrCache(i);
	}

	SynAttr();
	Creature::SynAttrToClient();
}

void Player::SetLastSceneInfo()
{
	m_lastSceneId = m_sceneId;
	m_lastPos = m_pos;
	m_lastMapId = m_lastMapId;
}

uint32_t Player::GetCampId()
{
	return GetAttr(C_CAMP_ID);
}

bool Player::IsSameCamp(Player* player)
{
	if (GetCampId() == player->GetCampId())
	{
		return true;
	}

	return false;
}

bool Player::IsTeammates(Player* player)
{
	if (GetAttr(C_TEAM_ID) > 0)
	{
		if (GetAttr(C_TEAM_ID) == player->GetAttr(C_TEAM_ID))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	return false;
}

bool Player::IsSameUnion(Player* player)
{
	if (GetAttr(C_UNION_ID) > 0)
	{
		if (GetAttr(C_UNION_ID) == player->GetAttr(C_UNION_ID))
		{
			return true;
		}
	}
	return false;
}

bool	 Player::IsNewPlayer()
{
	//return GetAttr(C_LEVEL) < NEW_PLAYER_MAX_LEVEL;
	return GetCampId() == ECamp_Type_None;
}

void Player::AddPkKillingValue(uint32_t addon)
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
	{
		part->AddPkKillingValue(addon);
	}
}

void Player::SendPvpKillingValue()
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
	{
		part->SendPvpKillingValue();
	}
}

void Player::SubPkKillingValue(uint32_t addon)
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
	{
		part->SubPkKillingValue(addon);
	}
}

uint32_t Player::GetPkKillingValue()
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
		return part->GetPkKillingValue();

	return true;
}

uint32_t Player::GetPkMode()
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
		return part->GetPkMode();

	return true;
}

void Player::SetPkMode(uint32_t pkMode)
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
	{
		part->SetPkMode(pkMode);
	}		
}

void	 Player::AddRedPlayer(Player* player)
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
	{
		part->AddRedPlayer(player);
	}
}


bool Player::IsRedPlayer(Player* player)
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
		return part->IsRedPlayer(player);

	return true;
}

bool Player::IsWanted() //是否被通缉
{
	PvpPart* part = dynamic_cast<PvpPart*>(GetPart(PART_PVP));
	if (part)
		return part->IsWanted();

	return true;
}

bool	 Player::IsFightState() //是否战斗状态
{
	return m_isFightState;
}

void	Player::ClearFightState() // 清空战斗状态
{
	m_isFightState = false;
}

bool Player::IsFriendSide(Creature* pCreature)
{
	if (pCreature == NULL || pCreature == this)
	{
		return true;
	}

	//活动中特殊玩法需求判断
	if (!g_GetGActivityMgr()->BossCanAttack(this, pCreature->GetCid()))
	{
		LogDebugFmtPrint("activity can not beattack!");
		return true;
	}

	//传送判断有特殊需求
	if (!pCreature->GetBeAttackFlag())
	{
		return true;
	}

	if (pCreature->HasBuffState(CREATURE_BUFF_STATE_WUDI))
	{
		return true;
	}

	const MapMapCfgInfo *pMapInfo = g_GetMapMapCfgTable()->GetMapMapCfgInfo(GetMapId());
	if (pMapInfo == nullptr)
	{
		return false;
	}

	if (pCreature->CreatureKind() != CREATURE_PLAYER
		&& pCreature->CreatureKind() != CREATURE_MONSTER
		&& pCreature->CreatureKind() != CREATURE_REBOT
		&& pCreature->CreatureKind() != CREATURE_NPC)
	{
		return true;
	}

	if (pCreature->CreatureKind() == CREATURE_PLAYER && pMapInfo->mapPk == MAP_PK_RULE_CAN_NOT_PK)
	{
		return true;
	}

	if (pCreature->CreatureKind() == CREATURE_PLAYER)
	{
		Player* player = dynamic_cast<Player*>(pCreature);
		if (player == nullptr || player == this)
		{
			return true;
		}

		//我和敌方任一一方处于安全区，则不让被攻击
		if (!player->IsCanBeAttackByCurrentPos() || !IsCanBeAttackByCurrentPos())
		{
			return true;
		}

		//所有模式下都不能攻击队友,以及队友的宠物，召唤物
		if (IsTeammates(player))
		{
			return true;
		}

		//如果对方是我的红名攻击玩家，我被攻击可以反击
		if (IsRedPlayer(player))
		{
			return false;
		}

		switch (GetPkMode())
		{
		//阵营模式
		case PK_MODE_CAMP:
		{
			//阵营模式下， 同一个阵营，同一个公会的玩家以及他们的宠物，召唤物都不能攻击
			//if (IsNewPlayer() || player->IsNewPlayer() || IsSameCamp(player) || IsSameUnion(player))
			//30级以下和平模式不可攻击任何玩家
			if (GetAttr(C_LEVEL) < NEW_PLAYER_MAX_LEVEL)
			{
				return true;
			}
			if (IsSameCamp(player))
			{
				if (player->IsWanted() == false)
				{
					return true;
				}
			}
			if (player->GetCampId() == 0 && player->GetPkMode() == PK_MODE_CAMP)
			{
				return true;
			}
			return false;
		}
		//工会模式
		case PK_MODE_COMMON:
		{
			//工会模式， 同一个公会的玩家以及他们的宠物，召唤物都不能攻击
			if (IsSameUnion(player))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		//善恶模式
		case PK_MODE_GOOD_EVIL:
		{
			if (IsSameCamp(player) || IsSameUnion(player) || player->GetCampId() == 0)
			{
				//善恶模式下，可以攻击同一阵营或同一公会下，被通缉的玩家
				if (player->GetPkKillingValue() <= 0)
				{
					return true;
				}
			}
			return false;
		}
		//杀谬模式, 只有不是队友就可攻击, 上面已判断
		case PK_MODE_KILLER:
		{
			return false;
		}
		default:
			return true;
		}
	}
	else if (pCreature->CreatureKind()== CREATURE_NPC)
	{
		Npc* pNpc = dynamic_cast<Npc*>(pCreature);
		if (pNpc && pNpc->GetNpcInfo()->npcFightType == 0)
		{
			return true;
		}

		switch (GetPkMode())
		{
			case PK_MODE_KILLER:
			{
				if (pNpc && pNpc->GetNpcInfo()->npcCamp == 0 && pNpc->GetNpcInfo()->npcFightType > 0)
				{
					return false;
				}
			}
		}
	}
	else if(pCreature->CreatureKind() == CREATURE_MONSTER)
	{
		Monster* pMonster = dynamic_cast<Monster*>(pCreature);
		if (pMonster)
		{
			if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_SUMMON)
			{
				if (pMonster->GetMonsterMasterCID() == GetCid())
				{
					return true;
				}
				//如果对方不可被攻击，返回true
				if (pMonster->GetMonsterFightType() == SUMMON_MONSTER_TYPE_CANNOT_BEATTACK_CANNOT_MOVE
						|| pMonster->GetMonsterFightType() == SUMMON_MONSTER_TYPE_CANNOT_BEATTACK_CAN_MOVE)
				{
					return true;
				}

				if (pMonster->GetMonsterMasterKind() == CREATURE_PLAYER)
				{
					//如果主人存在就 依据主人
					Creature* pOwner = GetScene()->GetCreature(pMonster->GetMonsterMasterCID());
					if (pOwner && pOwner != this)
					{
						return IsFriendSide(pOwner);
					}
				}
			}
			else if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_MOVE_BIAOCHE)
			{
				return true;
			}
			else if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_MOVE_TEAM_BIAOCHE) //对于公会镖车来说
			{
				if (GetAttr(C_CAMP_ID) > 0)	//有阵营
				{
					if (pMapInfo->mapPk == MAP_PK_RULE_CAN_NOT_PK || !IsCanBeAttackByCurrentPos())	//安全区 不能攻击公会镖车
					{
						return true;
					}

					if (GetAttr(C_CAMP_ID) == (int)pMonster->GetMonsterCampID()) //相同阵营不能攻击
					{
						return true;
					}
					else //不同阵营可以
					{
						return false;
					}
				}	//没有阵营不能攻击公会镖车
				else
				{
					return true;
				}
			}
			else if (pMonster->GetParentMonsterType() == PARENT_MONSTER_TYPE_MOVE_BIAOCHE_MONSTER)
			{
				//有公会说明是公会镖车怪物
				if (pMonster->GetMonsterUnionID() > 0)
				{
					if (GetAttr(C_UNION_ID) > 0)	//玩家有公会
					{
						if (GetAttr(C_UNION_ID) == (int)pMonster->GetMonsterUnionID()) //只有相同公会的才能攻击公会镖车怪物
						{
							return false;
						}
						else
						{
							return true;
						}
					}
					else
					{
						return true;
					}
				} //没有公会说明是个人镖车怪物
				else
				{
					//除非是个人镖车怪物的主人，不如不能攻击个人镖车怪物
					if (pMonster->GetMonsterMasterCID() == m_Cid)
					{
						return false;
					}
					return true;
				}
			}
		}
	}

	//通过表格探寻其他关系
	int first = gGetCreatureFriendShip(this);
	int second = gGetCreatureFriendShip(pCreature);
	return gGetCreatureVsCreature(first, second);
}

bool Player::DailyUpdate(uint64_t unixSec)
{
	for (int32_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
		{
			m_pPart[i]->DailyUpdate(unixSec);
		}
	}
	//竞技场挑战次数凌晨5点刷新
	m_arenaData.set_challengetimes(0);
	m_arenaData.set_updatetime(unixSec);

	m_activeDailyData.Clear();

	return true;
}

bool Player::WeekUpdate(uint64_t unixSec)
{
	for (int32_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
		{
			m_pPart[i]->WeekUpdate(unixSec);
		}
	}
	return true;
}


bool Player::DailyZeroUpdate(uint64_t unixSec)
{
	for (int32_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
		{
			m_pPart[i]->DailyZeroUpdate(unixSec);
		}
	}
	return true;
}

bool Player::WeekZeroUpdate(uint64_t unixSec)
{
	for (int32_t i = 0; i < PART_MAX; i++)
	{
		if (m_pPart[i])
		{
			m_pPart[i]->WeekZeroUpdate(unixSec);
		}
	}
	return true;
}

bool Player::InSonOfKillingStatus()
{
	if (GetPAttrValue(P_SONOFKILLING_TIME) > 0)
	{
		return true;
	}

	return false;
}

bool Player::RemitSonPKPunish()
{
	return g_GetGActivityMgr()->RemitSonPKPunish(GetSceneId());
}

bool Player::InWorldBossStatus()
{
	if (GetPAttrValue(P_CURSE_OF_FALL) > 0)
	{
		return true;
	}

	return false;
}

//判断是否在流放之地地图
bool Player::IsInJail()
{
	//找到流放之地地图
	const ConstantConstantCfgInfo *pJailMapID = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Jail);
	if (nullptr == pJailMapID)
	{
		LogErrFmtPrint("[logic] Player::C2AttrClearPoint.....nullptr == pJailMapID, id:%d ", EArg_ClearPoint_Jail);
		return false;
	}

	if (pJailMapID->constantdata == (int32_t)m_pScene->GetSceneId() )
	{
		return true;
	}
	return false;
}

void Player::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_UNDER_ATTACK:
	case EVENT_ATTACK_SOMEBODY:
	{
		skillAttackEvent  *pttackInfo = static_cast<skillAttackEvent*>(pContext);
		if (pttackInfo && (pttackInfo->attacker == m_Cid || pttackInfo->victim == m_Cid))
		{
			if (!m_isFightState)
			{
				m_isFightState = true;
				UpdateStateToClient();
			}

			if (pttackInfo->attacker == m_Cid)
			{
				AddSummonHateCid(pttackInfo->victim);
			}
			else
			{
				AddSummonHateCid(pttackInfo->attacker);
			}
		}	
		m_startFightStateTime = g_GetGlobalServerTime()->Tick();
	}
		break;
	case EVENT_CALC_FIGHT_POWER:
	{
		CalcPlayerFightPower(false);
		SyncToCenter(C_FIGHT_POWER);
	}
	break;
	case EVENT_CREATURE_DEAD:
	{
		//自己击杀的怪物
		AddAttrPA(P_KILL_MONSTER_NUM, 1, true);
	}
	break;
	default:
		break;
	}
}

//校验坐标，为true表示一致，false表示不一致
bool Player::CheckPos(Point3<float> &tmpPos,uint32_t distance)
{
	return point2LengthSquare(tmpPos, GetPos()) <= distance*distance;
}

void Player::AddArenaChallengeTimes()
{
	m_arenaData.set_challengetimes(m_arenaData.challengetimes() + 1);
	m_arenaData.set_updatetime(g_GetGlobalServerTime()->UnixSec());
}

uint32_t Player::GetArenaChallengeTimes()
{	
	return m_arenaData.challengetimes();
}

void Player::SetArenaBestRankId(uint32_t histroyId)
{
	m_arenaData.set_historyrankid(histroyId);
}

uint32_t Player::GetArenaBestRankId()
{
	return m_arenaData.historyrankid();
}

bool Player::ViewFliter(Creature* pCreature, float dict)
{
	////角色的视野裁剪包括宠物裁剪
	if (pCreature->CreatureKind() == CREATURE_DROP)
	{
		Drop *pDrop = dynamic_cast<Drop*>(pCreature);
		if (nullptr != pDrop && !pDrop->PlayerCanSeen(GetCid()))
		{
			return true;
		}
	}
	else if (pCreature->CreatureKind() == CREATURE_OBJECT)
	{
		Object *pObject = dynamic_cast<Object*>(pCreature);
		if (nullptr != pObject && !pObject->PlayerCanSeen(GetCid()))
		{
			return true;
		}
	}

	if (pCreature->CreatureKind() == CREATURE_MONSTER)
	{
		//如果是专属怪，则不是自己的主人，不让看见
		Monster * pMonster = dynamic_cast<Monster*>(pCreature);
		if (pMonster )
		{
			if (pMonster->IsOnlyOnwerOnePlayerMonster())
			{
				if (pMonster->IsOnlyMineMonster(m_Cid) && dict <= MAX_CHARACTER_SINGLERANGE_SQUARE)
				{
					return false;
				}
				else
				{
					return true;
				}
			}
		}
	}

	return Creature::ViewFliter(pCreature,dict);
}

//void Player::UpdateSeeLst()
//{
//	//如果自己是不被看见，则不能通知别人
//	if (!IsCanBeSeen())
//	{
//		return;
//	}
//
//	//根据提供的坐标位置，找对应场景里的生物
//	Uint64Lst newSeelst;
//	std::list<Creature*> notifyBeenSeeLst;
//
//	newSeelst.clear();
//	notifyBeenSeeLst.clear();
//
//	//FindCreatureInScene(newSeelst, m_pos, m_sightRange);
//
//	//FindCreatureInNineGride(newSeelst, m_pos);
//	//先查找this该生物最新的9宫格内的生物
//	FindSeeListInNineGrid(newSeelst);
//
//	//移除自己
//	newSeelst.remove(m_Cid);
//
//	CreaturesCreateData createData;
//	CreatureDestoryData destoryData;
//	Creature *pCreature = nullptr;
//
//	createData.Clear();
//	destoryData.Clear();
//
//	//查找一下旧视野里面有的但是新视野里面没的
//	for (Uint64Iter newIter = newSeelst.begin(); newIter != newSeelst.end(); newIter++)
//	{
//		if (std::find(m_seeLst.begin(), m_seeLst.end(), *newIter) == m_seeLst.end())
//		{
//			pCreature = m_pScene->GetCreature(*newIter);
//			if (pCreature)
//			{
//				notifyBeenSeeLst.push_back(pCreature);
//				//LogAlwaysFmtPrint("wachiing cids:%d --------creature:%d", m_Cid, *newIter);
//			}
//		}
//	}
//
//	//通知客户端需要离开视野的人
//	for (Uint64Iter oldIter = m_seeLst.begin(); oldIter != m_seeLst.end(); oldIter++)
//	{
//		if (std::find(newSeelst.begin(), newSeelst.end(), *oldIter) == newSeelst.end())
//		{
//			destoryData.add_cids(*oldIter);
//		}
//	}
//
//	//这里通知客户端删除生物 并且做视野移除
//	if (destoryData.cids_size() > 0)
//	{
//		for (int32_t i = 0; i < destoryData.cids_size(); i++)
//		{
//			CharIDType deleteCid = destoryData.cids(i);
//			pCreature = m_pScene->GetCreature(deleteCid);
//			if (pCreature)
//			{
//				//告诉我自己将对方从我的视野中移除
//				DelSeeLst(pCreature);
//
//				//告诉对方将我从他的视野中移除
//				pCreature->DelSeeLst(this);
//			}
//		}
//
//		SendDataToClient(LOGIC_TO_CLIENT_CREATURE_DESTORY, (ProtoBufBase*)(&destoryData));
//	}
//
//	//m_seeLst.swap(newSeelst);
//
//	//有新的生物进入视野
//	if (!notifyBeenSeeLst.empty())
//	{
//		//先让客户端创建生物实体，再执行该生物的被见逻辑
//
//		//MovePart * pPart = dynamic_cast<MovePart *>(GetPart(PART_MOVE));
//		std::list<Creature*>::iterator iter = notifyBeenSeeLst.begin();
//		for (; iter != notifyBeenSeeLst.end(); iter++)
//		{
//			//通知自己的角色属性信息
//			pCreature = *iter;
//			//LogAlwaysFmtPrint("start create monster cid=%d",pCreature->GetCid());
//			//将自己加入到对方的视野中
//			pCreature->AddSeeLst(this);
//			//再将对方加入到我自己的视野中
//			AddSeeLst(pCreature);
//
//			//CTODO该接口不应该放在此处去实现
//			//回调看见一个新生物，用于提高怪物AI反应
//			AddSeeNewCreature(pCreature);
//		}
//	}
//}

void Player::LogBase(LogTid logid, JsonObject &obj)
{
	obj.AddUInt32("tid", logid);
	obj.AddUInt32("chanid", m_chanId);
	obj.AddUInt32("uid", m_uid);
	obj.AddUInt64("rid", m_Cid);
	obj.AddUInt64("time", g_GetGlobalServerTime()->UnixSec());
	obj.AddUInt32("rjob", m_attrs[P_PROF]);
	obj.AddUInt32("rsex", m_attrs[P_GENDER]);
	obj.AddInt32("camp", m_attrs[P_CAMP_ID]);
	obj.AddUInt32("level", m_attrs[P_LEVEL]);
	obj.AddUInt32("race", m_attrs[P_RACE]);
	obj.AddUInt32("zid",  m_zid);
}

void Player::LoginLog()
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_LOGIN, obj);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player login log error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::LevUpLog()
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_LEVUP, obj);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player levup log error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::LoginOutLog()
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_LEAVE, obj);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player levup log error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::CurrencyLog(LogTid logid, uint32_t currencyid, uint32_t num, uint32_t source, const char* currencyName, uint64_t preValue, uint64_t newValue)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(logid, obj);

	if (source > S_END)
	{
		LogErrFmtPrint("source Id not have name, id:%d", source);
		obj.AddString("sourceName", "none");
	}
	else
		obj.AddString("souceName", l_source_name[source]);

	obj.AddString("currencyName", currencyName);
	obj.AddUInt32("currencyId", currencyid);
	obj.AddUInt32("num", num);
	obj.AddUInt32("source", source);
	obj.AddUInt64("preValue", preValue);
	obj.AddUInt64("newValue", newValue);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player currencylog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::MallLog(MallLogInfo& mall)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_MALL_BUY, obj);
	std::unordered_map<uint32_t, uint32_t>::iterator iter = mall.costMap.begin();
	std::unordered_map<uint32_t, uint32_t>::iterator iterEnd = mall.costMap.end();

	JsonObject mobj(&doc);

	for (; iter != iterEnd;)
	{
		const char* currencyName = g_GetAttrMgr()->GetCurrencyName(iter->first);
		if (currencyName == nullptr)
		{
			LogErrFmtPrint("mallLog currency Name == null, id:%d", iter->first);
			continue;
		}
		mobj.AddUInt32(currencyName, iter->second);
		iter++;
	}

	obj.AddString("name", mall.itemName);
	obj.AddObject("cost", mobj);
	obj.AddUInt32("discount", mall.discount);
	obj.AddUInt32("count", mall.count);
	obj.AddUInt32("price", mall.price);
	obj.AddUInt32("itemId", mall.itemId);

	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player mallLog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::RefineLog(uint32_t equipid, uint32_t preLvl, uint32_t newLvl, const string& equipName, const string& stoneName, uint32_t count, uint32_t gold, uint64_t preValue, uint64_t newValue, bool success)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_JING_LIAN, obj);

	obj.AddUInt32("equipId", equipid);
	obj.AddUInt32("prelevel", preLvl);
	obj.AddUInt32("newlevel", newLvl);
	obj.AddString("equipname", equipName);
	obj.AddString("stonename", stoneName);
	obj.AddUInt32("count", count);
	obj.AddUInt32("gold", gold);
	obj.AddUInt64("preValue", preValue);
	obj.AddUInt64("newValue", newValue);
	obj.AddBool("success", success);

	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player RefineLog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::InlayLog(uint32_t equipid, const string& equipName, const string& stoneName)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_BAOSHI, obj);

	obj.AddUInt32("equipId", equipid);
	obj.AddString("equipName", equipName);
	obj.AddString("stoneName", stoneName);

	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player InlayLog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::RuneLog(uint32_t equipid, const string& equipName, const string& runeName)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_FUWEN, obj);

	obj.AddUInt32("equipId", equipid);
	obj.AddString("equipName", equipName);
	obj.AddString("runeName", runeName);		//符文名

	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player RuneLog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::UnionUpgradeLog(uint32_t lvl, uint32_t contri, uint64_t preContri, uint64_t newContri, uint32_t gold, uint64_t preGold, uint64_t newGold)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_GH_JX, obj);

	obj.AddUInt32("level", lvl);
	obj.AddUInt32("contri", contri);	//消耗公会贡献
	obj.AddUInt64("preContri", preContri);
	obj.AddUInt64("newContri", newContri);
	obj.AddUInt32("gold", gold);
	obj.AddUInt64("preGold", preGold);
	obj.AddUInt64("newGold", newGold);

	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player UnionUpgradeLog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::GodLog(uint32_t clId, uint32_t count, uint32_t gold, const string& godName, uint32_t godLev)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_SHEN_GE, obj);

	const ItemItemCfgInfo *pItemCfg = g_GetItemItemCfgTable()->GetItemItemCfgInfo(clId);
	if (pItemCfg == nullptr)
	{
		const EquipEquipCfgInfo *pEquipItemCfg = g_GetEquipEquipCfgTable()->GetEquipEquipCfgInfo(clId);
		if (pEquipItemCfg != nullptr)
			obj.AddString("clName", pEquipItemCfg->name);
		else
		{
			obj.AddString("clName", "unkown");
			LogErrFmtPrint("Player::GodLog, cailiao id cannt find name, clId:%d", clId);
		}
	}
	else
		obj.AddString("clName", pItemCfg->name);
	obj.AddString("sgName", godName);
	obj.AddUInt32("count", count);
	obj.AddUInt32("sglev", godLev);
	obj.AddUInt32("gold", gold);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player shenge error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::ItemLog(LogTid logTid, JsonObject &obj, uint32_t source)
{
	if (source > S_END)
	{
		LogErrFmtPrint("source Id not have name, id:%d", source);
		obj.AddString("sourceName", "none");
	}
	else
		obj.AddString("souceName", l_source_name[source]);
	obj.AddUInt32("source", source);
	LogBase(logTid, obj);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player itemLog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::MissionAccpectLog(uint32_t missionid, string& missionName, uint32_t typeId)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_MISSION_ACCPECT, obj);
	obj.AddUInt32("id", missionid);
	obj.AddString("name", missionName);
	obj.AddUInt32("typeid", typeId);

	const TasktypeTasktypeCfgInfo *ptype = g_GetTasktypeTasktypeCfgTable()->GetTasktypeTasktypeCfgInfo(typeId);
	if (ptype == nullptr)
	{
		LogErrFmtPrint("task mission type err, typeid:%d, missionId:%d, missionName:%s", typeId, missionid, missionName.c_str());
		obj.AddString("typeName", "None");
	}
	else
		obj.AddString("typeName", ptype->remark);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player missionAccpet error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::MissionCompleteLog(uint32_t missionid, string& missionName, uint32_t typeId, uint32_t completeSec)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_MISSION_COMPLETE, obj);
	obj.AddUInt32("id", missionid);
	obj.AddString("name", missionName);
	obj.AddUInt32("typeid", typeId);
	obj.AddUInt32("cmptime", completeSec);

	const TasktypeTasktypeCfgInfo *ptype = g_GetTasktypeTasktypeCfgTable()->GetTasktypeTasktypeCfgInfo(typeId);
	if (ptype == nullptr)
	{
		LogErrFmtPrint("task mission type err, typeid:%u, missionId:%u, missionName:%s", typeId, missionid, missionName.c_str());
		obj.AddString("typeName", "None");
	}
	else
		obj.AddString("typeName", ptype->remark);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player missioncomplete error, cid:%lu, uid:%d", m_Cid, m_uid);

}

void Player::MissionFailLog(uint32_t missionid, string& missionName, uint32_t typeId, const char* reason)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_MISSION_ACCPECT, obj);
	obj.AddUInt32("id", missionid);
	obj.AddString("name", missionName);
	obj.AddUInt32("typeid", typeId);
	obj.AddString("reason", reason);

	const TasktypeTasktypeCfgInfo *ptype = g_GetTasktypeTasktypeCfgTable()->GetTasktypeTasktypeCfgInfo(typeId);
	if (ptype == nullptr)
	{
		LogErrFmtPrint("task mission type err, typeid:%d, missionId:%d, missionName:%s", typeId, missionid, missionName.c_str());
		obj.AddString("typeName", "None");
	}
	else
		obj.AddString("typeName", ptype->remark);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player missionfail error, cid:%lu, uid:%d", m_Cid, m_uid);
}

void Player::PayLog(const string& productId, const string& payOrder, uint32_t money, uint32_t diamond, uint32_t firstDiamond)
{
	rapidjson::Document doc;
	JsonObject obj(&doc);
	LogBase(TID_PAY, obj);
	obj.AddString("product", productId);
	obj.AddString("order", payOrder);
	obj.AddUInt32("money", money);
	obj.AddUInt32("diamond", diamond);
	obj.AddUInt32("firstDiamond", firstDiamond);
	bool bsuc = g_GetLogicService()->SendLogToLogServer(obj);
	if (bsuc == false)
		LogErrFmtPrint("player paylog error, cid:%lu, uid:%d", m_Cid, m_uid);
}

bool Player::CanTrans(ERetCode &ret,uint32_t dstSceneId, uint32_t dstMapId)
{
	//杀戮之子状态不能传送
	if (InSonOfKillingStatus())
	{
		ret = RET_ACTIVITY_SONOFKILLING_TRANS_ERROR;
		return false;
	}

	//神之遗骸状态不能传送
	if (InWorldBossStatus())
	{
		ret = RET_ACTIVITY_WORLD_BOSS_TRANS_ERROR;
		return false;
	}

	//工会驻地地图
	if (g_GetMapCfgMgr()->IsUnionHomeMap(dstMapId))
	{
		if (GetAttr(C_UNION_ID) <= 0)
		{
			ret = RET_UNION_NOT_JOIN;
			return false;
		}
		if (GetAttr(C_UNION_HOME_SCENE) != dstSceneId)
		{
			//不同的工会驻地场景ID
			ret = RET_UNION_NOT_TRANS_TO_OTHER_UNION_SCENE;
			return false;
		}
	}

	//处于活动状态不能切场景(工会战)
	/*if (!g_GetGActivityMgr()->CanTransScene(this))
	{
		ret = RET_PACKAGE_ITEM_LOST_CITY_FORBID;
		return false;
	}*/

	//处于流放之地，且杀戮值大于0，不能切找 
	const ConstantConstantCfgInfo *pJailMapID = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Jail);
	if (pJailMapID && m_pScene &&  m_pScene->GetSceneId() == (uint32_t)pJailMapID->constantdata)
	{

		PvpPart * pPart = dynamic_cast<PvpPart *>(GetPart(PART_PVP));
		if (pPart)
		{
			if (pPart->GetPkKillingValue() > 0)
			{
				ret = RET_CANTOT_TRANCE_FROM_JAIL;
				return false;
			}
		}
	}

	return true;
}


//pAttr 中按顺序存的各个属性的值 
void Player::GetLevelAddPointAttr(int64_t * pAttr, int num)
{
	//根据当前等级，获取基础属性值
	const RoleMasterCfgInfo *pMagicInfo = nullptr;
	const RoleShooterCfgInfo *pShooterInfo = nullptr;
	const RoleWarriorCfgInfo *pWarriorInfo = nullptr;
	const RoleAssassinCfgInfo *pAssassinInfo = nullptr;
	uint32_t i = 0;
	switch (m_attrs[P_PROF])
	{
	case ECHARACTER_PROF_WARRIOR:
		pWarriorInfo = g_GetRoleWarriorCfgTable()->GetRoleWarriorCfgInfo(m_attrs[P_LEVEL]);
		if (!pWarriorInfo)
		{
			LogErrFmtPrint("warrior lev cfg error");
			return ;
		}
		for (i = 0; i < pWarriorInfo->vecRoleWarriorAttributeCfg.size(); i++)
		{
			if (pWarriorInfo->vecRoleWarriorAttributeCfg[i].Type >= 1 && pWarriorInfo->vecRoleWarriorAttributeCfg[i].Type <= 6)
			{
				pAttr[pWarriorInfo->vecRoleWarriorAttributeCfg[i].Type-1] = pWarriorInfo->vecRoleWarriorAttributeCfg[i].Value;
			}
		}
		break;
	case ECHARACTER_PROF_ASSASSIN:
		pAssassinInfo = g_GetRoleAssassinCfgTable()->GetRoleAssassinCfgInfo(m_attrs[P_LEVEL]);
		if (!pAssassinInfo)
		{
			LogErrFmtPrint("passassin lev cfg error");
			return ;
		}

		for (i = 0; i < pAssassinInfo->vecRoleAssassinAttributeCfg.size(); i++)
		{
			if (pAssassinInfo->vecRoleAssassinAttributeCfg[i].Type >= 1 && pAssassinInfo->vecRoleAssassinAttributeCfg[i].Type <= 6)
			{
				pAttr[pAssassinInfo->vecRoleAssassinAttributeCfg[i].Type-1] = pAssassinInfo->vecRoleAssassinAttributeCfg[i].Value;
			}
		}
		break;
	case ECHARACTER_PROF_MAGICIAN:
		pMagicInfo = g_GetRoleMasterCfgTable()->GetRoleMasterCfgInfo(m_attrs[P_LEVEL]);
		if (!pMagicInfo)
		{
			LogErrFmtPrint("warrior type size != value size");
			return ;
		}

		for (i = 0; i < pMagicInfo->vecRoleMasterAttributeCfg.size(); i++)
		{
			if (pMagicInfo->vecRoleMasterAttributeCfg[i].Type >= 1 && pMagicInfo->vecRoleMasterAttributeCfg[i].Type <= 6)
			{
				pAttr[pMagicInfo->vecRoleMasterAttributeCfg[i].Type-1] = pMagicInfo->vecRoleMasterAttributeCfg[i].Value;
			}
		}

		break;
	case ECHARACTER_PROF_ARCHER:
		pShooterInfo = g_GetRoleShooterCfgTable()->GetRoleShooterCfgInfo(m_attrs[P_LEVEL]);
		if (!pShooterInfo)
		{
			LogErrFmtPrint("warrior type size != value size");
			return ;
		}

		for (i = 0; i < pShooterInfo->vecRoleShooterAttributeCfg.size(); i++)
		{
			if (pShooterInfo->vecRoleShooterAttributeCfg[i].Type >= 1 && pShooterInfo->vecRoleShooterAttributeCfg[i].Type <= 6)
			{
				pAttr[pShooterInfo->vecRoleShooterAttributeCfg[i].Type-1] = pShooterInfo->vecRoleShooterAttributeCfg[i].Value;
			}
		}

		break;
	default:
		break;
	}

	//再加上已加的点数
	pAttr[0] += m_attrs[P_ATTR_POINT_POWER];
	pAttr[1] += m_attrs[P_ATTR_POINT_INTELLIGENCE];
	pAttr[2] += m_attrs[P_ATTR_POINT_AGILITY];
	pAttr[3] += m_attrs[P_ATTR_POINT_PHYSIQUE];
	pAttr[4] += m_attrs[P_ATTR_POINT_ENDURANCE];
	pAttr[5] += m_attrs[P_ATTR_POINT_PRECISION];

	return;
}

//发送T除玩家信息到中心服
bool Player::SendKickPlayerToCenter()
{
	LogicToCenterKickPlayerReq req;
	req.set_cid(m_Cid);

	g_GetLogicService()->SendDataToCenter(EMODULE_ID_LOGIN, LOGIC_TO_CENTER_KICK_PLAYER,&req);
	return true;
}

//同步获取经验到客户端
void Player::SyncExpToClient(uint32_t baseExp, uint32_t otherExp)
{
	NoticeShowExpRsp rsp;
	rsp.set_baseexp(baseExp);
	rsp.set_otherexp(otherExp);

	SendDataToClient(LOGIC_TO_CLIENT_SHOW_EXP, &rsp);
}

//收到中心服的排名信息
void Player::ReqCenterRankingListIndex(uint32_t type, uint32_t index)
{
	TitlePart * pPart = dynamic_cast<TitlePart*>(m_pPart[PART_TITLE]);
	if (pPart)
	{
		pPart->AddRankingList(type, index);
	}
}

//激活内挂道具
void Player::ActiveLeiGuaItem(int32_t activeTime)
{
	if (m_i64StartUseLeiGuaItem<=0)
	{
		m_i64StartUseLeiGuaItem = Time::Now().sec();
		m_iLeiGuaAllTime = activeTime * 60 * 60;

		//启动倒计时定时
		g_GetTimerAxis()->SetTimer(enTime_LeiGua, m_iLeiGuaAllTime * 1000, this, 1);

		SyncLeiGuaLeftTimeToClient((uint64_t)m_iLeiGuaAllTime);
	}
	else
	{
		m_iLeiGuaAllTime += activeTime * 60 * 60;

		//先停以前的倒计时，再启新的倒计时
		g_GetTimerAxis()->KillTimer(enTime_LeiGua,this);
		int64_t leftTime = m_iLeiGuaAllTime - (Time::Now().sec() - m_i64StartUseLeiGuaItem);
		if (leftTime>0)
		{
			g_GetTimerAxis()->SetTimer(enTime_LeiGua, leftTime * 1000, this, 1);
		}

		SyncLeiGuaLeftTimeToClient((uint64_t)leftTime);
	}
	return;
}

//同步内挂有效时间到客户端,单位秒
void Player::SyncLeiGuaLeftTimeToClient(uint64_t leftTime)
{
	NoticeLeiGuaLeftTimeRsp rsp;
	rsp.set_lefttime(leftTime);

	SendDataToClient(LOGIC_TO_CLIENT_LEIGUA_LEFT_TIME, &rsp);
}

//是否在内挂时间内
bool Player::IsLeiGuaActiveTime()
{
	return m_i64StartUseLeiGuaItem > 0;
}

//获取玩家活动信息
PlayerActiveAnswerData & Player::GetPlayerAnswerData()
{
	return m_activeData;
}
//设置玩家活动信息
void Player::SetPlayerAnswerData(PlayerActiveAnswerData & data)
{
	m_activeData.CopyFrom(data);
}
//清除玩家身上的答题活动
bool Player::ClearAnswerActiveData()
{
	m_activeData.clear_answerlist();
	m_activeData.Clear();
	return true;
}


//获取玩家每日答题活动
PlayerActiveAnswerData & Player::GetPlayerDailyAnswerData()
{
	return m_activeDailyData;
}
//设置玩家每日答题活动信息
void Player::SetPlayerDailyAnswerData(PlayerActiveAnswerData & data)
{
	m_activeDailyData = data;
}
//清除玩家身上的每日答题活动
bool Player::ClearDailyAnswerActiveData()
{
	m_activeDailyData.Clear();
	return true;
}


//添加专属怪物的cid
void Player::AddOnwerMyselfMonsterCid(CharIDType cid)
{
	m_createMyselfMonsterCid.push_back(cid);
}

//判断是否是自己专属怪
bool Player::IsOnlyOwnerMonster(CharIDType cid)
{
	if (std::find(m_createMyselfMonsterCid.begin(), m_createMyselfMonsterCid.end(), cid) != m_createMyselfMonsterCid.end())
	{
		return true;
	}
	return false;
}
